-
Notifications
You must be signed in to change notification settings - Fork 3k
$stateChangeStart -> event.preventDefault() forces wrong url change. #1699
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
I agree the behavior is odd, but what state do you expect the user to end up in? By the way, usually people do a |
Yes, I do have redirect to login in my code - I just cut it out here, for brevity. As for the state, I think it's pretty obvious - this is a $stateChangeStart, right? If it's prevented, then user remains in the state he started from. Simply put, the state don't change. I see no reason, why preventing state results in changing the url. |
Hi sebastian,
However, if you do have a redirect in your code, then this behavior is odd, and I'd need more details. Can you make a plunk? |
Yes, that's it. I have the login redirect right after the preventDefault (edited my initial code), pretty much the same as you've described. But it will never reach it, as preventDefault resets the url and then triggers the "otherwise" condition on urlRouter. I do understand that in this particular case, there's no previous state and maybe the url reset makes sense. But it collides with otherwise, which prevents the redirect from working. I'm not very good at providing sample codes on these external services, sorry. This should do, though. angular 1.3.8, newest ui-router. |
Put your code in a plunk and reproduce it, then I'll take a look |
I happen to have come across the same issue. Here's a fork of your plunk, with just a couple lines added: I think this captures what @sebastian-zarzycki was trying to accomplish. We want the default route to be "home", unless for some reason it doesn't pass some filter. So we do a check (line 29) and then redirect with a I think the confusion is that the syntax As an aside, in the meantime, it seems the workaround would be to have the "otherwise" route be a dummy placeholder, and always check state transitions to make sure the user goes somewhere correct. That way even if "otherwise" gets loaded unintentionally, it has no functionality associated with it. |
Pretty much, thanks for this, Michael. |
Same issue here. Does anyone know of a workaround? |
The work around I found was:- $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
if (notLoggedIn) {
event.preventDefault();
return $state.go('login');
}
return;
}); The key for me was to return the new state |
Thanks @adammartin1981, works for me. |
@adammartin1981 looking at the source, I could be wrong, but I don't think the return value of an event is checked. angular-ui-router.js version 0.2.15 line 3229 if ($rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams).defaultPrevented) { All it does is check if the defaultPrevented function was called on the event. |
My case is a bit more complicated. The browser back button is broken (it loops). The following does not break the history API: $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
if (notLoggedIn) {
event.preventDefault();
$state.go('login');
}
}); The following does: $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
event.preventDefault();
$timeout(function() {
if (notLoggedIn) {
$state.go('login');
} else {
$state.go(toState, toParams);
}
});
}); (obviously, I'm not just setting a timeout for the heck of it, but I'm doing some ajax call) My fix is the following, in angular-ui-router.js version 0.2.15 line 3231: if ($rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams).defaultPrevented) {
$rootScope.$broadcast('$stateChangeCancel', to.self, toParams, from.self, fromParams);
//$urlRouter.update(); // this line causes the issue in case of browser nav
return TransitionPrevented;
} The problematic case with this $urlRouter.update call is the following: Since angular-ui-router version 0.2.15 line 2064: update: function(read) {
if (read) {
location = $location.url();
return;
}
if ($location.url() === location) return; // toStateUrl !== from fromStateUrl
$location.url(location); // $location.url(fromStateUrl);
$location.replace();
}, I suppose there is a good reason for that var event = $rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams);
if (event.defaultPrevented) {
$rootScope.$broadcast('$stateChangeCancel', to.self, toParams, from.self, fromParams);
if (event.noUpdate !== true) {
$urlRouter.update();
}
return TransitionPrevented;
} event.preventDefault();
event.noUpdate = true; It may not look very clean, but I can't think of another way around. |
closing this since it seems like a workaround for the original problem is there. @FLO-G if you are having a separate problem (seems like it?) then please open a new issue for that. |
I'm sorry, but #1699 (comment) does not work for me. event.preventDefault() still executes a state change to the otherwise route and this create an infinite loop in my app. Anyone else with this problem? I fully agree with #1699 (comment), in my opinion a preventDefault()-Call should prevent the event from happen - and nothing else. If i want a following state change, i will do it by myself. |
@michaelcox i tried the "dummyState"-approach you mentioned here #1699 (comment).
But what then? If i listen to |
After some issue studying, rewriting my otherwise statement to this
solved my (Sorry, don't know where i copied that from) |
Same issue here. Got stuck in an infinite loop when state transition from Thanks. |
@readme42 thanks :) I had issue with Ionic app, Your code fixed it! |
@readme42 thanks :) Your solution worked for me too. |
@readme42 thanks :) |
@eddiemonge Can't this be fixed in source?
|
#1699 (comment) solved it for me |
@hakib Could you describe the issue you had with the infinite looping in more detail? I have a feeling I am running into something similar... Perhaps post code snippets of before and after please? |
@DanielCaspers I had an infinite loop because I was also intercepting |
Thanks @hakib. This inspired me in finding my problem, although mine wasn't related to this. In the situation I was working on, I believe it was a logic error because |
.state('login', {
url: '/login',
templateUrl: 'templates/login.html',
controller: 'LoginCtrl',
onEnter: function($state, Auth){
if(Auth.isAuth()){
$state.go('tab.neworder');//place u want to go when login
}
}
}) use this this work perfectly |
Was experiencing this issue myself with an outdated version of ui-router v0.2.15 and tried all the work arounds to no avail. For anyone experiencing this issue, ui-router v0.4.2 has now rectified the issue. |
@readme42 I also had the same issue in the latest version of Ionic v1. I was receiving '$rootScope:infdig] 10 $digest() iterations reached. Aborting!' error. I am using this code to check: The following code fixed it. |
in my main controller:
states definition (just the relevant portion, other states are obviously there):
console output
so it first loads the application
http://localhost/app/
then it applies the first "when" condition on urlRouter level, so it goes to /home.
http://localhost/app/#!/home
Then, the $stateChangeStart triggers, checks that user is not logged is (own logic), and does event.preventDefault(). At this stage, instantly, the url is reset
http://localhost/app/#!/
and somehow, the "otherwise" condition triggers in
http://localhost/app/#!/error/not-found
This 3rd step is unexpected and breaks the flow of the application (preventing interferes with urlRouter)
The text was updated successfully, but these errors were encountered: