Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UI-Router's resolve functions are only called once

Tags:

I was going to use ui-routers resolve feature to inject some readiliy resolved promises into my controllers.

I used the example plnkr to make an example. Consider these nested states: route1 and route1.list. I have a resolve function called abc defined on route1. Now when I navigate to route1 for the first time, abc is called and will be resolved. Now when I navigate to route1.list and back to route1, abc is not called again.

http://plnkr.co/edit/mi5H5HKVAO3J6PCfKSW3?p=preview

I guess this is intentional, but consider this use-case: the resolve function retrieves some data via http and should be refreshed/invalidated at some point, maybe on every state change. Is there some way to do this when using nested states? If the resolve function was called on every inject I could implement it any way I want: Return the old, resolved promise or create a new one.

I have only briefly tested this, but if the states were not nested things would work as I expected. Giving up on nested states because of this stinks though. And having the resolve dependencies available in nested states is actually nice.

like image 534
Christoph Dietze Avatar asked Mar 29 '14 12:03

Christoph Dietze


2 Answers

Supplying the option reload:true to go() / transtionTo() / ui-sref does the trick :-) Thanks to Designing the Code for pointing me in this direction. The solution is a bit different though, so I write up this answer.

Reload is documented as follows:

reload (v0.2.5) - {boolean=false}, If true will force transition even if the state or params have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd use this when you want to force a reload when everything is the same, including search params.

The direct way is to change every ui-sref link into something like this: <a ui-sref="route1" ui-sref-opts="{reload: true}">.

To avoid supplying the option at every link I wrote a decorator around $state (see also http://plnkr.co/edit/mi5H5HKVAO3J6PCfKSW3?p=preview):

 myapp.config(function($provide) {   $provide.decorator('$state', function($delegate) {     var originalTransitionTo = $delegate.transitionTo;     $delegate.transitionTo = function(to, toParams, options) {       return originalTransitionTo(to, toParams, angular.extend({         reload: true       }, options));     };     return $delegate;   }); }); 
like image 191
Christoph Dietze Avatar answered Sep 22 '22 03:09

Christoph Dietze


Try $state.reload();

It will force resolve the resolves again. Though think there is some issue related to this where controllers aren't reloaded. (ui.router n00b here as well)

like image 32
Designing the Code Avatar answered Sep 21 '22 03:09

Designing the Code