utilizzare il router Angular 2 per passare valori diversi allo stesso componente

Il codice riportto di seguito serve dello stesso componente AppComponent per tre routes diversi, tra cui / , /route3 e /route3 .

Il problema è che le properties; di properties; e bodyHTML di AppComponent non modificano i valori quando vengono selezionati i diversi routes.

Quali modifiche specifiche devono essere apportte al codice riportto di seguito in modo che l'applicazione bodyHTML valori diversi per title e bodyHTML quando ciascuno dei diversi routes viene selezionato dall'utente?

Di seguito sono riportti i passi per riprodurre il problema su qualsiasi computer in pochi minuti :


Crea l'applicazione seme:


In primo luogo, ho creato un'applicazione per seme utilizzando Angular-CLI nei seguenti passaggi:

 cd C:\projects\angular-cli ng new routes-share-component cd C:\projects\angular-cli\routes-share-component ng serve 

Modifica solo 4 file:


Successivamente, ho cambiato solo 4 file come segue:

Ho aggiunto app.routing.ts al seguente contenuto:

 import { Routes, RouterModule } from '@angular/router'; import { AppComponent } from './app.component'; const appRoutes: Routes = [ { path: '', component: AppComponent }, { path: 'route2', component: AppComponent }, { path: 'route3', component: AppComponent } ]; export const routing = RouterModule.forRoot(appRoutes); 

Ho cambiato app.component.ts per diventare le seguenti:

 import { Component, OnInit, OnChanges } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Router } from '@angular/router'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit, OnChanges { title = 'This is the title!'; bodyHTML = 'Here is the content!' constructor(private _router:Router, private route:ActivatedRoute) { console.log('inside the constructor!'); console.log(route.url); console.log(_router.url); } ngOnInit() { console.log('inside ngOnInit()'); let currentUrl = this._router.url; /// this will give you current url console.log(currentUrl); if(currentUrl=='/'){this.title='Home Page Title';this.bodyHTML='Body goes here.';} if(currentUrl=='/route2'){this.title='Route 2 Title';this.bodyHTML='Body goes here.';} if(currentUrl=='/route3'){this.title='Route 3 Title';this.bodyHTML='Body goes here.';} console.log(this.route.url); } ngOnChanges() { console.log('inside ngOnChanges()!'); let currentUrl = this._router.url; /// this will give you current url console.log(currentUrl); if(currentUrl=='/'){this.title='Home Page Title';this.bodyHTML='Body goes here.';} if(currentUrl=='/route2'){this.title='Route 2 Title';this.bodyHTML='Body goes here.';} if(currentUrl=='/route3'){this.title='Route 3 Title';this.bodyHTML='Body goes here.';} console.log(this.route.url); } } 

Analogamente, app.component.html stato semplificato nei seguenti app.component.html :

 <div style="text-align:left"> <h1>{{title}}</h1> <p>{{bodyHTML}}</p> </div> 

E app.module.ts diventa il seguente, con app.routing.ts incluso:

 import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { routing } from './app.routing'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, routing ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } 

Si noti che il block ngOnInit() printingto nella console, ma che il block ngOnChanges() NON. Ciò significa che il titolo è sempre il titolo di Home Page Title , non import quale path è selezionato.

Quali modifiche specifiche devono essere apportte al codice precedente in modo che each path stampi valori diversi nel browser per title e bodyHTML ?


Suggerimenti di BeetleJuice:


Suggerimento per @ BeetleJuice, ho provato la seguente nuova versione di AppComponent , ma sta visualizzando errori di compilazione alle linee routerSub:Subscription e alla linea this.routerSub = this.router.events.filter(....) .

 import { Component, OnInit, OnChanges } from '@angular/core'; import { NavigationEnd, Router, ActivatedRoute } from '@angular/router'; import { Subscription } from 'rxjs/Subscription'; import 'rxjs/add/operator/filter'; import 'rxjs/add/operator/map'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { title = 'This is the title!'; bodyHTML = 'Here is the content!'; routerSub:Subscription; constructor(private router:Router) { console.log('inside the constructor!'); console.log(router.url); } ngOnInit(){ // listen to NavigationEnd events this.routerSub = this.router.events.filter(e=>e instanceof NavigationEnd) // capture the new URL .map(e.NavigationEnd => e.url) .subscribe(url => { /* TODO: use URL to update the view */ }); } // When the component is destroyed, you must unsubscribe to avoid memory leaks ngOnDestroy(){ this.routerSub.unsubscribe(); } } 

Che altro deve essere cambiato?

Due cose da realizzare:

  • Quando Angular si avvia verso un nuovo path che utilizza lo stesso componente, non reinizializza il componente. Quindi il tuo ngOnInit esegue solo la prima volta che il componente viene caricato.

  • ngOnChanges non viene triggersto quando una properties; di un componente cambia. Viene triggersto quando una properties; associata al dato (come indicato da @Input() someProp ) viene modificata da un componente padre. Vedi i documenti . Quindi i tuoi ngOnChanges non vengono innescati.

Un modo per aggiornare il model quando il path cambia ma il componente non deve iniettare il router, ascoltare i Router.events osservabili e reactjs alla modifica del path

app.component.ts

 import {NavigationEnd, Router} from '@angular/router'; import { Observable } from 'rxjs/Observable'; import { Subscription } from 'rxjs/Subscription'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/filter'; ... routerSub:Subscription; ngOnInit(){ // listen to NavigationEnd events this.routerSub = this.router.events.filter(e=>e instanceof NavigationEnd) // capture the new URL .map((e:NavigationEnd) => e.url) .subscribe(url => { /* TODO: use URL to update the view */ }); } // When the component is destroyed, you must unsubscribe to avoid memory leaks ngOnDestroy(){ this.routerSub.unsubscribe(); } 

A proposito, potrebbe non essere una buona idea avere più routes che risolvono nello stesso componente. Prendi in considerazione invece un path parametrizzato !