Angular-ui Router get two states active in parallel

All we need is an easy explanation of the problem, so here it is.

I need to use two states in parallel, one for my page and an other for a modal with several sub states.
Right now calling the modal state will wipe out my page since the page state changed.

Create a child state child of my page wouldn’t be a solution since the modal will be used on several pages.

Example:

$stateProvider
.state('user', {}) // page
.state('bookshelf', {}) // page
.state('books', {}) // modal
.state('books.read', {}) // sub state of modal

So if I’m on user and open my modal then the state would change to books, my modal would then have the content but the page content will be wiped out.

How do I fix it?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

I believe the way you’re looking to do this is not possible with UI.Router currently. What you’re describing is a modal component (which would ideally be written as a directive), which tracks it’s state independently from the main state.

The way to think about it, is that UI.Router works by creating a state tree. At any given time you can only be looking at one branch of the tree. You can go deeper down a branch (ie: book, book.open, book.open.checked), but you can’t be in two places at once.

Another issue with the problem above is how do you serialize the state of the two different trees into one url? It’s not to say it can’t be done, it’s just a hard problem to solve.

Checkout these issues:

Also checkout these repos, they might be further along the lines of solving the problem.

As far as solving your immediate problem, I think the ‘easiest’ way would be to ditch controlling the state of the modal inside your state config.

Instead, I would add some sort of root or abstract state, and then track whether the modal is open there. Then, you can communicate between controllers using events as shown here. Note: There are performance implications with listening to $rootScope, so be sure to research those. However (someone feel free to correct me), the implementation here doesn’t have those problems, because the AppCtrl is never destroyed.


Jan 15, 2015 Edit

Turns out this is a pretty popular use case, and one of the core contributors to UI Router maintains a plugin/addition called UI Router Extras

It also includes utilities for lazy loading, called “Future States” which are very helpful.

That being said, one feature I’m hoping to get time to work on is maintaining all state within the URL (or perhaps, local storage) and allowing for reusable state “components”. The latter is in the UI Router roadmap as well.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply