How to share information with child routes in Angular 2?

I have an application that will look like this:

/:partner/login /:partner/tools /:partner/other 

Currently, using 2.0.0-rc.5 , I can simply create routes that look exactly the same as above. However, the drawback of this approach is that each component must independently extract the partner parameter. Thus, the declaration of the login path will look like this:

 { path: ':partner/login', component: LoginComponent } 

And the LoginComponent will look like this:

 export class LoginComponent implements OnInit { partner: string; constructor(private _route: ActivatedRoute) { } ngOnInit() { this._route.params.forEach(p => { this.partner = p[`partner`]; }); } } 

While this is manageable with three routes, conceptually, I really want to say that I have a PartnerComponent that has child routes login , tools , etc. Routing will look like this:

 { path: ':partner', component: PartnerComponent children: [ { path: 'login', component: LoginComponent}, { path: 'tools', component: ToolsComponent} ] } 

And using TypeScript inheritance, I can create a basic component for each child, for example:

 export class BaseComponent implements OnInit { partner: string; constructor(private _route: ActivatedRoute) { } ngOnInit() { this._route.parent.params.forEach(p => { this.partner = p[`partner`]; }); } } 

and child components will look like this:

 export class LoginComponent extends BaseComponent { constructor(route: ActivatedRoute) { super(route); } ngOnInit() { super.ngOnInit(); } } 

While the above works, it feels a little dirty to find the parent route. I know if I change the hierarchy, I only need to change it in the database, but still

Is there a cleaner way to exchange information between the parent and its child route components.

If this were a more traditional parent / child relationship, we would just use data binding between them to pass this information.

+5
source share
2 answers

What you can do is use Resolve protection for the parent route, so the data will be downloaded for any route :partner .

A Resolve will look like this:

 import { Injectable } from '@angular/core'; import { Router, Resolve, ActivatedRouteSnapshot } from '@angular/router'; import { Partner } from './partner.model'; import { Api } from './api.service'; @Injectable() export class PartnerResolve implements Resolve<Partner> { constructor(private api: Api, private router: Router) {} resolve(route: ActivatedRouteSnapshot): Observable<Partner> { let id = +route.params['partner']; return this.api.getPartner(id); } } 

Then your route should include PartnerResolve so that it does not load until the data has been requested and not available:

 { path: ':partner', component: PartnerComponent, resolve: { partner: PartnerResolve }, children: [ { path: 'login', component: LoginComponent}, { path: 'tools', component: ToolsComponent}, ] } 

And your PartnerComponent will just get it:

 ngOnInit() { this.route.data.forEach((data: { partner: Partner }) => { this.partner = data.partner; }); } 

And your child components will use:

 ngOnInit() { this.route.parent.data.forEach((data: { partner: Partner }) => { this.partner = data.partner; }); } 
+1
source

Another way to pass data from parent to child is to use @Input .

 @Component({ selector: 'partner', template: 'partner.html' directives: [LoginComponent] }) export class PartnerComponent { partner: string; } @Component({ selector: 'login', template: 'login.html' }) export class LoginComponent { @Input() loginPartner: string; //passed in from the parent } //partner.html <div> <login [login-partner]='partner'></login> </div> 

Link https://angular.io/docs/ts/latest/cookbook/component-communication.html

-1
source

All Articles