Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular-ui Router get two states active in parallel

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?

like image 762
Jonathan de M. Avatar asked Mar 10 '14 23:03

Jonathan de M.


1 Answers

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:

  • https://github.com/angular-ui/ui-router/issues/119
  • https://github.com/angular-ui/ui-router/issues/384
  • https://github.com/angular-ui/ui-router/issues/475

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

  • https://github.com/afterglowtech/angular-detour
  • https://github.com/stu-salsbury/angular-couch-potato

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.

like image 160
Jon Jaques Avatar answered Oct 05 '22 01:10

Jon Jaques