feat(router): allow passing `state` to routerLink directives (#27198)

This value will get written to the `history.state` entry.

FW-613 (related)
Related to #24617

PR Close #27198
This commit is contained in:
Jason Aden 2018-11-16 10:10:11 -08:00 committed by Igor Minar
parent 67f4a5d4bd
commit 73f6ed9be1
2 changed files with 64 additions and 0 deletions

View File

@ -77,6 +77,27 @@ import {UrlTree} from '../url_tree';
* </a>
* ```
*
* You can provide a `state` value to be persisted to the browser's History.state
* property (See https://developer.mozilla.org/en-US/docs/Web/API/History#Properties). It's
* used as follows:
*
* ```
* <a [routerLink]="['/user/bob']" [state]="{tracingId: 123}">
* link to user component
* </a>
* ```
*
* And later the value can be read from the router through `router.getCurrentTransition.
* For example, to capture the `tracingId` above during the `NavigationStart` event:
*
* ```
* // Get NavigationStart events
* router.events.pipe(filter(e => e instanceof NavigationStart)).subscribe(e => {
* const transition = router.getCurrentTransition();
* tracingService.trace({id: transition.extras.state});
* });
* ```
*
* The router link directive always treats the provided input as a delta to the current url.
*
* For instance, if the current url is `/user/(box//aux:team)`.
@ -104,6 +125,7 @@ export class RouterLink {
@Input() skipLocationChange !: boolean;
// TODO(issue/24571): remove '!'.
@Input() replaceUrl !: boolean;
@Input() state?: {[k: string]: any};
private commands: any[] = [];
// TODO(issue/24571): remove '!'.
private preserve !: boolean;
@ -185,6 +207,7 @@ export class RouterLinkWithHref implements OnChanges, OnDestroy {
@Input() skipLocationChange !: boolean;
// TODO(issue/24571): remove '!'.
@Input() replaceUrl !: boolean;
@Input() state?: {[k: string]: any};
private commands: any[] = [];
private subscription: Subscription;
// TODO(issue/24571): remove '!'.
@ -237,6 +260,7 @@ export class RouterLinkWithHref implements OnChanges, OnDestroy {
const extras = {
skipLocationChange: attrBoolValue(this.skipLocationChange),
replaceUrl: attrBoolValue(this.replaceUrl),
state: this.state
};
this.router.navigateByUrl(this.urlTree, extras);
return false;

View File

@ -1878,6 +1878,36 @@ describe('Integration', () => {
expect(location.path()).toEqual('/team/22/simple?q=1#f');
})));
it('should support history state',
fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => {
const fixture = createRoot(router, RootCmp);
router.resetConfig([{
path: 'team/:id',
component: TeamCmp,
children: [
{path: 'link', component: LinkWithState},
{path: 'simple', component: SimpleCmp}
]
}]);
router.navigateByUrl('/team/22/link');
advance(fixture);
const native = fixture.nativeElement.querySelector('a');
expect(native.getAttribute('href')).toEqual('/team/22/simple');
native.click();
advance(fixture);
expect(fixture.nativeElement).toHaveText('team 22 [ simple, right: ]');
// Check the history entry
const history = (location as any)._history;
expect(history[history.length - 1].state.foo).toBe('bar');
expect(history[history.length - 1].state).toEqual({foo: 'bar', navigationId: history.length});
})));
});
describe('redirects', () => {
@ -4576,6 +4606,13 @@ class RelativeLinkCmp {
class LinkWithQueryParamsAndFragment {
}
@Component({
selector: 'link-cmp',
template: `<a [routerLink]="['../simple']" [state]="{foo: 'bar'}">link</a>`
})
class LinkWithState {
}
@Component({selector: 'simple-cmp', template: `simple`})
class SimpleCmp {
}
@ -4770,6 +4807,7 @@ class LazyComponent {
RelativeLinkCmp,
DummyLinkWithParentCmp,
LinkWithQueryParamsAndFragment,
LinkWithState,
CollectParamsCmp,
QueryParamsAndFragmentCmp,
StringLinkButtonCmp,
@ -4797,6 +4835,7 @@ class LazyComponent {
RelativeLinkCmp,
DummyLinkWithParentCmp,
LinkWithQueryParamsAndFragment,
LinkWithState,
CollectParamsCmp,
QueryParamsAndFragmentCmp,
StringLinkButtonCmp,
@ -4826,6 +4865,7 @@ class LazyComponent {
RelativeLinkCmp,
DummyLinkWithParentCmp,
LinkWithQueryParamsAndFragment,
LinkWithState,
CollectParamsCmp,
QueryParamsAndFragmentCmp,
StringLinkButtonCmp,