fix(router): restore 'history.state' object for navigations coming from Angular router (#28108) (#28176)
When navigations coming from Angular router we may have a payload stored in state property. When this exists, set extras's state to the payload. PR Close #28176
This commit is contained in:
parent
3d156162af
commit
df76a2048b
|
@ -920,7 +920,15 @@ export class Router {
|
||||||
// hybrid apps.
|
// hybrid apps.
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const {source, state, urlTree} = currentChange;
|
const {source, state, urlTree} = currentChange;
|
||||||
this.scheduleNavigation(urlTree, source, state, {replaceUrl: true});
|
const extras: NavigationExtras = {replaceUrl: true};
|
||||||
|
if (state) {
|
||||||
|
const stateCopy = {...state};
|
||||||
|
delete stateCopy.navigationId;
|
||||||
|
if (Object.keys(stateCopy).length !== 0) {
|
||||||
|
extras.state = stateCopy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.scheduleNavigation(urlTree, source, state, extras);
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
this.lastLocationChangeInfo = currentChange;
|
this.lastLocationChangeInfo = currentChange;
|
||||||
|
|
|
@ -159,6 +159,59 @@ describe('Integration', () => {
|
||||||
expect(navigation.extras.state).toEqual({foo: 'bar'});
|
expect(navigation.extras.state).toEqual({foo: 'bar'});
|
||||||
})));
|
})));
|
||||||
|
|
||||||
|
it('should set history.state when navigation with browser back and forward',
|
||||||
|
fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => {
|
||||||
|
router.resetConfig([
|
||||||
|
{path: '', component: SimpleCmp},
|
||||||
|
{path: 'simple', component: SimpleCmp},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const fixture = createRoot(router, RootCmp);
|
||||||
|
let navigation: Navigation = null!;
|
||||||
|
router.events.subscribe(e => {
|
||||||
|
if (e instanceof NavigationStart) {
|
||||||
|
navigation = <Navigation>router.getCurrentNavigation()!;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const state = {foo: 'bar'};
|
||||||
|
router.navigateByUrl('/simple', {state});
|
||||||
|
tick();
|
||||||
|
location.back();
|
||||||
|
tick();
|
||||||
|
location.forward();
|
||||||
|
tick();
|
||||||
|
|
||||||
|
expect(navigation.extras.state).toBeDefined();
|
||||||
|
expect(navigation.extras.state).toEqual(state);
|
||||||
|
})));
|
||||||
|
|
||||||
|
it('should not error if state is not {[key: string]: any}',
|
||||||
|
fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => {
|
||||||
|
router.resetConfig([
|
||||||
|
{path: '', component: SimpleCmp},
|
||||||
|
{path: 'simple', component: SimpleCmp},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const fixture = createRoot(router, RootCmp);
|
||||||
|
let navigation: Navigation = null!;
|
||||||
|
router.events.subscribe(e => {
|
||||||
|
if (e instanceof NavigationStart) {
|
||||||
|
navigation = <Navigation>router.getCurrentNavigation()!;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
location.replaceState('', '', 42);
|
||||||
|
router.navigateByUrl('/simple');
|
||||||
|
tick();
|
||||||
|
location.back();
|
||||||
|
advance(fixture);
|
||||||
|
|
||||||
|
// Angular does not support restoring state to the primitive.
|
||||||
|
expect(navigation.extras.state).toEqual(undefined);
|
||||||
|
expect(location.getState()).toEqual({navigationId: 3});
|
||||||
|
})));
|
||||||
|
|
||||||
it('should not pollute browser history when replaceUrl is set to true',
|
it('should not pollute browser history when replaceUrl is set to true',
|
||||||
fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => {
|
fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => {
|
||||||
router.resetConfig([
|
router.resetConfig([
|
||||||
|
|
Loading…
Reference in New Issue