Angular 2 introduces native support for an awesome feature that seems to be frequently overlooked: matrix URL parameters. Essentially, these allow you to attach an arbitrary amount of data inside a URL to any routing level in Angular, and giving you the ability to read that data out as a regular URL parameter.
The code, links, and a live example of this are available at .
Begin with the code created at the end of the How to do it... section in Implementing nested views with route parameters and child routes.
Your goal is to pass arbitrary data to both the ArticleList
and ArticleDetail
levels of this application via only the URL.
routerLink
arrays are processed serially, so any string that will become part of the URL that is followed by an object will have that object converted into matrix URL parameters. It will be easier to understand this by example, so begin by passing in some dummy data to the ArticleList
view from routerLink
:
[app/root.component.ts] import {Component} from '@angular/core'; @Component({ selector: 'root', template: ` <h1>Root component</h1> <a [routerLink]="['']"> Default</a> <a [routerLink]="['article', {listData: 'foo'}]"> Article</a> <router-outlet></router-outlet> ` }) export class RootComponent {}
Now, if you click on this link, you will see your browser navigate to the following path while still successfully rendering the ArticleList
view:
/article;listData=foo
To access this data, simply extract it from the ActivatedRoute
params:
[app/article-list.component.ts] import {Component} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; @Component({ template: ` <h3>Article List</h3> <p *ngFor="let articleId of articleIds"> <a [routerLink]="[articleId]"> Article {{articleId}} </a> </p> ` }) export class ArticleListComponent { articleIds:Array<number> = [1,2,3,4,5]; constructor(private activatedRoute_:ActivatedRoute) { activatedRoute_.params .subscribe(params => { console.log('List params:'); console.log(window.location.href) console.log(params); }); } }
When the view is loaded, you'll see the following:
List params: /article;listData=foo Object {listData: "foo"}
Awesome! Do the same for the detail view:
[app/article-list.component.ts] import {Component} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; @Component({ template: ` <h3>Article List</h3> <p *ngFor="let articleId of articleIds"> <a [routerLink]="[articleId, {detailData: 'bar'}]"> Article {{articleId}} </a> </p> ` }) export class ArticleListComponent { articleIds:Array<number> = [1,2,3,4,5]; constructor(private activatedRoute_:ActivatedRoute) { activatedRoute_.params .subscribe(params => { console.log('List params:'); console.log(window.location.href) console.log(params); }); } }
Add the same amount of logging to the detail view:
[app/article-detail.component.ts] import {Component} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; @Component({ template: ` <h3>Article Detail</h3> <p>Showing article {{articleId}}</p> <a [routerLink]="'../'">Back up</a> ` }) export class ArticleDetailComponent { articleId:number; constructor(private activatedRoute_:ActivatedRoute) { activatedRoute_.params .subscribe(params => { console.log('Detail params:'); console.log(window.location.href) console.log(params); this.articleId = params['articleId'] }); } }
When you visit a detail page, you'll see the following logged:
Detail params: /article;listData=foo/1;detailData=bar Object {articleId: "1", detailData: "foo"}
Very interesting! Not only is Angular able to associate different matrix parameters with different routing levels, but it has combined both the expected articleId
parameter and the unexpected detailData
parameter into the same Observable
emission.
Angular is able to seamlessly convert from a routing array containing a matrix param object to a serialized URL containing the matrix params, then back into a deserialized JavaScript object containing the parameter data. This allows you to store arbitrary data inside URLs at different levels, without having to cram it all into a query string at the end.
Notice that when you click on Back up in the detail view, the listData
URL param is preserved. Angular will dutifully maintain the state as you navigate throughout the application, so using matrix parameters can be a very effective way of storing stateful data that survives navigation or page reloads.