The correct way to share data with child routes through a router? router 3.0.0-alpha.7

Last week, I really started digging around in Angular 2 and (like many others, apparently), had serious headaches around routing. I started working with router 3.0.0-alpha.7. I really want to share some of the data received in the base component with these child components. Here is my route configuration.

[{ path: 'base/:id', component: BaseComp, children: [{ path: '', component: OverviewComp }, { path: 'docs', component: DocsComp }] }] 

When hitting the base route, I get some data through the service based on the id parameter. As soon as these data are received, I would like them to cascade children. I was hoping it would be as simple as putting @Inputs on OverviewComp and DocsComp, but I quickly realized that there was no way in the template to do this, given that <router-outlet> is the actual component of the template. Derp.

Does anyone have any idea what is the best way to do this?

  • Should I work with an earlier version of the router (legacy router)?

  • Should the id parameter be ported to child components?

  • If the child components just got into the service to get the same data (cached)?

+8
angular angular2-routing
source share
2 answers

Should I work with an earlier version of the router (legacy router)?

The challenge is to evolve as fast as Angular2 overthrows their routing concept :). Although, make sure you don't go out of date. It was still in beta when they decided to specify it as "obsolete", so you probably don't want to use obsolete unstable routing.

Should the id parameter move to child components?

I would say it depends on your structure. Suppose you have many such routes.

 /user/:id/.... 

It is absolutely wise to allow the user in the component that listens for / user /: id and do this once, and not in each of the child components. However, there is a drawback if you want the user to be available on your child routes. Using the service is suitable for this purpose, but you need to deal with the asynchronous nature of HTTP requests. When the child route is activated and their components are processed, the backend call has not yet completed. Thus, you cannot access your services directly from your child component, you also need to get observable. This adds a bit of complexity to your service.

Another way is to preferentially exceed the add-in and eliminate all the data necessary for the child component. This means that for such a route

 /user/:id/process/:id/edit 

you need to solve both the user and the process, and probably the second call to the "process" depends on the "user", which must be resolved in advance. If you have a lot of children's routes with a lot of identifiers, you can get a little tired to solve this problem.

Remember that if you route the /user/:id segment to a component that should display some user data, and you need this user data in child components, you should also choose the first option. It makes no sense to make several calls of the same data.

If child components just got into the service to get the same data (Cached)?

Yes, on the same route, absolutely. This saves bandwidth and server resources. Moreover, this can be dangerous, since the server can send different data in each subsequent request (at least if you do not specify the version of the requested document). Of course, whenever a user starts a new route, choose for yourself if you present cached data or request an update from the server.

+3
source share

I think I had a similar dilemma, and that’s how I deal with such situations.

1. Target and input parameters

When I want to break down a child component from the main component, I will try to see if this is a different kind of system object or not (basically, if I need a full routing for it or I can solve my data link using only the property as the target / input) Do not forget:

Angular insists that we declare the target property as the input property. If we do not, Angular will reject the binding and throw an error.

Check out part3 from the ng2 tutorial: https://angular.io/docs/ts/latest/tutorial/toh-pt3.html

1. Routing

For different components, you can define a new route and then retrieve data using two methods:

1.1. From the parameters of the route and the service (you should use the service method for any data loading, so you can reorganize access to the data and keep the component aside and focus on supporting the view). You should use route parameters only for filters or tasks of small tasks, and not for data transmission. Here is a possible component:

Object1Routes

 import { RouterConfig } from '@angular/router'; import { Object1Dashboard } from './object1.dashboard'; import { Object1Edit } from './object1.edit'; export const Object1Routes: RouterConfig = [ { path: 'object1', component: Object1Dashboard, 'children': [ <...> ,{ path: 'edit/:id', component: Object1Edit } ] } ]; 

Object1Edit

 import { Component, OnInit, OnDestroy } from '@angular/core'; import { Router, ActivatedRoute } from '@angular/router'; import { Object1Service } from './services/object1/object1.service'; import { Object1Model } from './models/object1/object1.model'; @Component({ selector: 'object1-edit', templateUrl: './object1/object1.edit.html', directives: [] }) export class Object1Edit implements OnInit, OnDestroy { model = new Object1Model; sub:any; editId:number; constructor( private route: ActivatedRoute, private router: Router, private serviceData: Object1Service ) { } onSubmit(d:Object1Model) { this.model = d; this.router.navigate(['/object1']); } ngOnInit() { this.sub = this.route.params.subscribe(params => { this.editId = +params['id']; // (+) converts string 'id' to a number this.serviceData.getObject1ById(this.editId).then(data => { this.model = data; }); }); }); } ngOnDestroy() { this.sub.unsubscribe(); } } 

1.2. Just out of service

Object1Routes

 import { RouterConfig } from '@angular/router'; import { Object1Dashboard } from './object1.dashboard'; import { Object1List } from './object1.list'; export const Object1Routes: RouterConfig = [ { path: 'object1', component: Object1Dashboard, 'children': [ { path: '', component: Object1List } <...> ] } ]; 

Object1List

 import { Component, OnInit, OnDestroy } from '@angular/core'; import { Router, ActivatedRoute } from '@angular/router'; import { Object1Service } from './services/object1/object1.service'; import { Object1Model } from './models/object1/object1.model'; @Component({ selector: 'object1-list', templateUrl: './object1/object1.list.html' }) export class Object1List implements OnInit, OnDestroy { constructor( private route: ActivatedRoute, private router: Router, private serviceData:Object1Service ) { } modelArray:Object1Model[]; selectedId:number; private sub: any; onSelect(model:Object1Model) { console.log('Select ' + model.code); let link = ['/object1/edit', model.id]; this.router.navigate(link); } onDelete(model:Object1Model) { console.log('Delete : ' + model.code); this.serviceData.delObject1ById(model.id); } ngOnInit() { this.sub = this.route .params.subscribe(params => { this.selectedId = +params['id']; this.serviceData.getAllObject1().then(data => this.modelArray = data); }); } ngOnDestroy() { if (this.sub) { this.sub.unsubscribe(); } } } 

Hope this helps. Let me know if you have a different opinion or if I missed something.

The code provided is based on Angular 2.0.0-rc.2 and @ angular / router 3.0.0-alpha.7.

Also check out this article on the principle of single responsibility : https://blog.8thlight.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html

+2
source share

All Articles