Skip to content
Permalink
Browse files

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
  • Loading branch information...
jasonaden authored and IgorMinar committed Nov 16, 2018
1 parent 67f4a5d commit 73f6ed9be1a3452d71a8d7cee9958f0076cdf0bb
Showing with 64 additions and 0 deletions.
  1. +24 −0 packages/router/src/directives/router_link.ts
  2. +40 −0 packages/router/test/integration.spec.ts
@@ -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;
@@ -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,

0 comments on commit 73f6ed9

Please sign in to comment.
You can’t perform that action at this time.