Closed NeoGenet1c closed 7 years ago
Agreed, that's undesired behavior.
are you using pushstate or hashbang urls?
Would you be able to add {location: 'replace'}
to your transition options when doing the initial redirect?
I think this should be solvable by the router. If the initial transition was caused by a url synchronization then when the final state is activated, the url should be replaced.
In the redirect code we could probably enable { location: 'replace' }
if the old transition was initiated by a url sync (options.source === 'url'
) and no prior location:
option was provided (by checking the original targetState()
)
I use pushstate URLs ($locationProvider.html5Mode({ enabled: true }).
Can I (somehow) define transition options inside StateDefinition's Object or do I have to use hooks and detect it is first run and first redirect?
Are you using redirectTo
?
it would be something like this:
redirectTo: trans => {
let $state = trans.router.stateService;
let firstTrans = trans.$id === 0;
let options = { location: (firstTrans ? 'replace' : true) };
return $state.target("home.foo", {}, options);
}
Yep, haven't realised that redirectTo
can take a callback :) This is what indeed DOES work for me in Angular1:
parentState.redirectTo = function( $transition ) {
var $state = $transition.router.stateService,
firstTransition = angular.isUndefined( $transition.id ),
options = { location: ( firstTransition ? 'replace' : true ) };
return $state.target( childrenState.name, $transition.params(), options);
}
Btw, Thanks for the great work on new router @christopherthielen!
@NeoGenet1c @christopherthielen Have you solved this issue? I found it may be near these codes:
$rootScope.$watch(function $locationWatch() {
var oldUrl = trimEmptyHash($browser.url());
var newUrl = trimEmptyHash($location.absUrl());
var oldState = $browser.state();
var currentReplace = $location.$$replace;
var urlOrStateChanged = oldUrl !== newUrl ||
($location.$$html5 && $sniffer.history && oldState !== $location.$$state);
if (initializing || urlOrStateChanged) {
initializing = false;
$rootScope.$evalAsync(function() {
var newUrl = $location.absUrl();
var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
$location.$$state, oldState).defaultPrevented;
// if the location was changed by a `$locationChangeStart` handler then stop
// processing this location change
if ($location.absUrl() !== newUrl) return;
if (defaultPrevented) {
$location.$$parse(oldUrl);
$location.$$state = oldState;
} else {
if (urlOrStateChanged) {
setBrowserUrlWithFallback(newUrl, currentReplace,
oldState === $location.$$state ? null : $location.$$state);
}
afterLocationChange(oldUrl, oldState);
}
});
}
And as urlOrStateChanged is true, the function afterLocationChange is called which makes rul rechange.
@chaserstrong Yep. Christopher's solution worked for me.
This plunker demonstrates the issue: http://plnkr.co/edit/3arZH4m0iuaUlVBw06So?p=preview
This will be fixed in rc.1: http://plnkr.co/edit/Xu8FkXNkAFvD6BEJsHvR?p=preview
Note: .otherwise()
doesn't use { replace: true }
by default, which is another potential issue but would be a breaking change.
UI router v1.0.0-beta.3 and angular v1.5.9
When an app loads its initial state for the first time and it contains a redirect, the transition graph looks something like following:
State A [redirected] -> State B [success]
However, if a user clicks on the back button, UI router tries to jump back to State A causing another redirect (meaning that nothing happens). In this case, transitions look like this:
State A [redirected] -> State B [ignored]
Finally, another click on the back button will send me back to wherever I was before the application/first state loaded (eg. Google's SERP).
I would expect that a first click on the back button will send a user to a previous page. This issue only occurs if the very first loaded state is a redirect - if I get to a state with a redirect through ui-sref link within my own app, the back button click will send me back right away.