-
Notifications
You must be signed in to change notification settings - Fork 3k
Preventing Resolve On URL Change Without State Reload #2796
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Is it the resolve for that state and maybe not a child or parent state or something? |
The reload option can only be used to force state(s) to reload. It can't be used the way you describe however. Reload: false won't prevent a params change from re-entering a state. In 0.x the only support for your use case is a query param with reloadOnSearch=false. In 1.0 you would use dynamic params. |
@christopherthielen Would it be more accurate then that notify: false is preventing the state from reloading? And if that is the case, wouldn't it make sense that notify would also prevent the resolve block from initiating? As I understand it, notify: false is preventing the standard state change events from firing. If that is the case, then what initiates the resolve block? It couldn't be the $stateChangeStart event because that is theoretically not firing. @eddiemonge The resolves that are rerun are those for the current state. I recognize that a possible solution might be to pass a squashed param as a part of the new url and the resolve functions could then check that before running. However, we have 5 resolve functions in this current state, all of which would need the check as well as any other state which needed to do this. That seems like the wrong thing to do and a headache to maintain. The best situation I could envision is one in which an option param is passed to prevent resolve, whether that's via notify or something else. |
Your suggested workaround might work, but you'd have to cache the resolve results in a service and have a bunch of logic to manage that correctly. The only supported mechanisms are On a side note, I do not recommend anyone use |
Alright, finally had some time to work on this. Here's what I ended up doing: For the state: .state('name', {
url: '/path/:changer',
params: {
overwriteReload: {
value: false,
squash: true
}
},
resolve: {
doSomething: function($stateParams) {
if ($stateParams.overwriteReload === true) {
return;
}
// Do something
},
doSomethingElse: function($stateParams) {
if ($stateParams.overwriteReload === true) {
$stateParams.overwriteReload = false;
return;
}
// Do something else
}
}
}) The last checker in the resolve must set the overwriteReload back to false to prevent weirdness with inheritance in new states. For the actual overwrite (which I have placed inside a service in my application): $state.go($state.$current.self.name,
{changer: 'somethingNew', overwriteReload: true},
{location: 'replace', notify: false}); Even though it may use notify: false which is not recommended, it does the job correctly in this instance. So far as I can tell anyway. The resolve logic does not run for those marked with the if block and the current controllers/state do not change or reload. The url is changed but no new entry is put into the browser history. |
For completeness, I looked at |
I am having this issue on consecutive calls. I call something like:
First time, the
Call stack is coming from:
|
Hello @calebeno, I have actually the same issue : please see here Can you developp your answer ? Cause actually, if I use $scope.go() into my returned promise, I enter in a loop (the $state reload and reload... event if the option parameter: reload set to false). And if I use $location, the $state is reload twice (so the result function is called twice too) |
@ShakurOo, I don't believe that (typeof $state.params.ville == 'undefined') Which should probably be: (typeof $stateParams.ville == 'undefined') Other than that, I'm not sure exactly what to advise? My solution uses a squashed param to prevent reload. It's possible that could work for you? |
I will also comment that, while my solution does work, it does not fix the underlying problem. However, based on the replies so far, I don't think we can expect this to be fixed in |
Thank's for your quick reply :) The issue is : When the $promise function is resolved, I have to change the URL (for build a correct url, because the user can type with space, special chars, ...). So, for do this I tried to call $location service and redefine a new URL in the promise callback : But with it, the resolve function is called again (I don't need it). If I try to change the URL with : This time the resolve function is called in loop ! (So my service which returns data is called endlessly ... (the client freeze). And |
@ShakurOo If you want to use the solution I posted, you should wrap the functionality of your resolve function in an if block which checks for a param. I would recommend doing something like this in your state definition:
Then your resolve would have: resolve: {
init: function() {
if (!preventResolve) {
// Your stuff
...
// if this is the last function in your resolve block set prevent back to false
preventResolve = false;
}
}
} Then, when you call Also, in my case I have the controller calling a service which initiates the $state.go. Maybe this could be useful to you as well? |
@calebeno Yes I understood ! But if i waiting until the controller is loaded, the ui-view will load the template... The interest for using the resolve function is it prevent the loading of the template view. The data is loaded before the view is displayed. There is another sujet here, I going to look if someone has any others tips. Thank's you :) |
I am experiencing the same behavior as @calebeno where I want to update the state but do not want to process the resolves again. @christopherthielen a simple $state.go() option called resolve which you can set to false would skip the processing of resolves. Thanks |
We can't have an option "to skip processing of resolves" because this would cause fundamental inconsistencies in the state machine. When a state is being entered, its resolves must be processed. However, by using Here's how it works:
Closing because I think the original question is answered by Please open a new issue (and reference this one) if there are other use cases not solved by |
The resolve skipping technique above is working for me, but I can't seem to find a combination of transition options ( |
I've been working on a project and am having an issue with the resolve block. This is my use case: When transitioning to a state, a resolve block is completed. Once in the new state, a component determines whether or not the url needs to be changed. The goal is to remain in exactly the same state, but to modify the url. However, when I make the url modification using something like this:
$state.go($state.$current.self.name, {newparams}, {location: 'replace', reload: false, notify: false});
The entire state remains the same and the url is updated, which is the desired behavior. However, the resolve block is then called again, adding unnecessary server requests. Is it not possible to prevent the resolve block from running? I feel like using reload: false should prevent this.
Note: I commented something similar on issue #2146. Since it was closed and this is slightly different I have reposted as a different issue here.
The text was updated successfully, but these errors were encountered: