-
Notifications
You must be signed in to change notification settings - Fork 3k
$stateChangeSuccess is fired before previous state $scope is destroyed in 0.2.16 #2485
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
Yeah, destroying scopes is necessarily deferred by the I'm not sure there's anything we can do here, but I'm open to suggestions... |
I think a change in the order of events should be considered a breaking change and should be highlighted in the changelog. It's very easy to accidentally depend on the order of events without realising you're doing it. Highlighting it in the changelog will let people know to look out for cases where they do this. Semantically I think it makes more sense for $destroy to trigger before $stateChangeSuccess. I have no idea how difficult that is to achieve so I don't expect the behaviour to revert. It's something of an edge case so unless a lot of people come forward with issues it's probably fine to leave it. I'll look into writing a test to verify the order of events firing (if one doesn't exist already) so we know if it changes in the future. |
+1 |
+1 we had the same issue as well as we were relying on the $destroy event to reset some services when the view change |
+1 same issue for us as well |
Hi guys, sorry for your trouble. Again, this was the result of a fix for people with animated view transitions, where controller scopes were getting destroyed too early, causing rendering issues during animation. @christopherthielen I guess we could try to detect whether people are using animation and opt them into the old behavior...? :-/ |
+1 Change it back. :( |
This also introduces ambiguity in terms of the "current" state and its properties. We got a bug where params that used to be there at the time of navigation are no longer available. I understand the need for the original fix, but this is definitely a breaking change. |
+1 we are also having issues because of this change |
@4Ants I don't think we can change it back, sorry. I don't have time to look at it right now, but I'm open to suggestions on how we could improve it without reintroducing broken behavior. |
This change breaks our angular-spinners library which relied on the If we can no longer depend on this Edit: We decided to change our behavior so that new spinners with the same name override old spinners registered with that name. It's not ideal but it's better than making all users of both angular-spinners and ui-router key a manual unregister call from |
This is a breaking change. |
I've also had my code broken but appreciate the work that went into the last releases. @nateabele and @christopherthielen do you have any suggestions on how we might refactor our code so that we are able to 'destroy before create'? |
To those affected by this:The ui-router philosophy is that the state machine drives the application. The views are secondary things that happen in response to the state changing. They're somewhat non-deterministic (you could pop them in and out of existence with an ng-if, for instance). I consider the views almost as side effects. See if you can refactor your code to use the state machine hooks and events instead (onExit, $stateChangeSuccess) to perform your exiting cleanup. Otherwise: for the time, please revert to 0.2.15; We'll try to come up with a solution and plan a 0.2.18 (le sigh...)
I'll echo @nateabele 's sentiment. Let us know if you have any ideas. Consider the issue that this change was addressing: #1643 where the view being animated out had its scope destroyed, and thus the outgoing view was mangled. Have a look at this code: We could really use the help right now. There are a lot of proverbial balls in the air right now, and it's tough to keep up. |
I created PR #2497 which selects the "static" (synchronous) renderer in the following cases:
Try this version which has my code from pr #2497: https://rawgit.com/christopherthielen/842ee74c30299093aa07/raw/200f188394d5b05de68e092e6b5c60905671e3ca/angular-ui-router.0.2.18-pr.js Here is @bighuggies fiddle with pr #2497 http://plnkr.co/edit/fpE6CBzRN7zCGFng3bcb?p=preview tested against 1.2.28 through 1.5.0-rc01 with and without |
@christopherthielen I've tested your PR against our app using the So at least for our use case, this does seems to fix the issues we were having. Thanks for the quick response! |
Out of curiosity, I'm not quite sure how I WOULD refactor my code to better initialize controllers. The 'resolve' element works great for passing data into a controller, but I'm not sure how to run initialization procedures when switching between child states, without resorting to $stateChangeSuccess. @christopherthielen or @nateabele, what is the ideal way to handle initialization of a controller upon state changes that share the same controller? |
@ledhed2222 Can you be more specific? In general, my controllers:
I don't find the need to manage lifecycle in the controller beyond what I listed above. What is your controller doing that you need to handle scope |
Thanks @christopherthielen For one, I'm quite new to Angular and this lib. I've inherited some code that, based on your comment above, might not have been written ideally. Here's the general idea: Parent state A (should be abstract, but wasn't implemented that way) All of these states share the same controller X. X needs to re-initialize some scope variables and call functions defined within the controller whenever the view moves between states B and C. As I write this, I suppose it could all be refactored with a big 'resolve' dictionary, injecting everything into X. Is that the pattern? |
When the view moves between states B and C, B is exited and C is entered. A new instance of the controller X is instantiated/injected within the context of state C and C's resolves. Are you concerned about the second copy of the controller X that is active within the context of parent state A? (state A is retained; it is neither exited nor reentered) |
Hmm, I guess that's not what I'm seeing - switching between the two child states doesn't seem to instantiate a new controller but rather uses the same instance. Now, I didn't realize that a parent state's controller instance will persist (or even that the parent's controller would be instantiated if we're in a child); could that have to do with this issue? Also, this is probably getting off topic of the main issue here. If there's a better place for me to continue this discussion please let me know. And thank you! |
since nobody else has commented about the PR in a week, I'm pulling the trigger |
feat(ui-view): Add noanimation attribute to specify static renderer. closes #2485
I understand the need for this change. But would it not make sense for the $stateChangeSuccess event to trigger after the previous state is destroyed, as the state is not fully transitioned yet before that? On another side not there are other issues with this change as well, such as a states $stateParams changing because you are on another state before it is destroyed |
Also would it be possible to have a config on uirouter to disable this? Having to set noanimate on all uiviews in the app if you don't want to disable all ngAnimations are very brittle. |
Be careful not to conflate views with states. In ui-router, the transition is complete when the states are all entered and the States don't get destroyed, only scopes do. Scopes get destroyed when their DOM is destroyed (basically) or in the case of animation, when the ui-view is animating out because it is being replaced.
Can you provide more details? The
possibly... |
The $stateParams object injected into controllers are definitely mutated. We watch it for changes to the params to update the page running if the url is changed. This actually caused most of the issues we had after this change was introduced. (Previously these watches were removed before the the ui-view transitioned because the scope was destroyed) |
If anyone needs it i made this little directive to globally force the old way to render on all ui-views
|
@kenborge nice. @nateabele and I are reconsidering the changes merged in via #2346 attempting to fix #1643. stay tuned. |
…fix(ui-view) use static renderer if animations not enabled . Closes angular-ui#2485
This fiddle shows the difference in order of $destroy and $stateChangeSuccess between 0.2.15 and 0.2.16
https://jsfiddle.net/n3emkeo7/
This change broke our application, and I think it could be quite a significant breaking change.
My guess is that it's something to do with 1be1379 (unconfirmed).
Our use case:
We have a navigation control which listens for
$stateChangeSuccess
and subsequently updates the URL using$state.go
.In 0.2.15 this was fine if you navigated to a different page, the navigation control was destroyed before the
$stateChangeSuccess
event was fired, so the control would only redirect the user if they were navigating to a child state.In 0.2.16 the
$stateChangeSuccess
event is fired before the control is destroyed, causing the user to be trapped on the page with the navigation control regardless of if they are trying to navigate away from the page.The text was updated successfully, but these errors were encountered: