2016-05-24 39 views
5

Utilizzo di Angular 2 rc.1 e TypeScript. Sto avendo un sacco di problemi nel passare i parametri di instradamento al mio componente quando il componente viene caricato in una sub-tratta. Io uso il pacchetto @angular/router-deprecated.Angular 2: come passare i parametri del percorso a subroute?

Nel mio componente radice, ho configurato i percorsi in quanto tali:

@RouteConfig([ 
    {path:'/top', name:'Top', component: EndPointComponent}, 
    {path:'/sub/...', name:'Sub', component: MiddleManComponent} 
]) 

Ecco la componente endpoint dove ho tentativo di leggere i parametri

import {Component} from '@angular/core'; 
import {RouteParams} from '@angular/router-deprecated'; 
@Component({ 
    template: 'Route Params: {{routeParams.params | json}}' 
}) 
export class EndPointComponent{ 
    constructor(private routeParams:RouteParams){} 
} 

Ecco la middleman component con il subroute a EndPointComponent

import {Component} from '@angular/core'; 
import {RouteConfig, ROUTER_DIRECTIVES} from '@angular/router-deprecated'; 
import {EndPointComponent} from "./endpoint.component"; 

@Component({ 
    directives: [ROUTER_DIRECTIVES] 
    template: `<router-outlet></router-outlet>` 
}) 
@RouteConfig([ 
    {path: '/end', name: 'End', component: EndPointComponent, useAsDefault: true} 
]) 
export class MiddleManComponent {} 

I parametri possono essere letti con successo dall'oggetto routeParams di EndPointComponent quando il componente viene caricato dalla route di livello superiore (ad esempio: la route denominata "Top" nel componente root). Tuttavia, i parametri sono sempre vuoti quando si naviga su EndPointComponent passando da MiddleManComponent (ad esempio: tramite la route denominata "Sub" nel componente root).

I router per bambini puliscono i parametri dai genitori prima di risolvere i percorsi? Non ha molto senso quindi scommetto che mi manca qualcosa. La mia domanda è semplicemente: come posso passare i parametri del percorso a una sub-tratta?

PS: ho provato a costruire un plunker su demo this setup ma mi sono arreso quando non riuscivo a capire perché l'applicazione non viene caricata.

risposta

4

I percorsi figlio ottengono effettivamente la propria istanza di RouteParams, distinti dal percorso principale. Questo viene fatto per evitare la denominazione delle collisioni e facilitare l'incapsulamento del componente indirizzato.

Un modo per condividere i parametri di un percorso principale con un componente caricato da un percorso figlio è attraverso un servizio.

@Injectable() 
export class RouteParamService { 
    constructor(private routeParams: RouteParams) {} 

    get params() { 
    return this.routeParams.params; 
    } 
} 

@Component({ 
    template: 'Route Params: {{routeParams.params | json}}' 
}) 
export class EndPointComponent{ 
    constructor(private routeParams:RouteParamService){} 
} 

@Component({ 
    directives: [ROUTER_DIRECTIVES] 
    template: `<router-outlet></router-outlet>`, 
    providers: [RouteParamService] 
}) 
@RouteConfig([ 
    {path: '/end', name: 'End', component: EndPointComponent, useAsDefault: true} 
]) 
class MiddleManComponent() { } 

Il RouteParamService sarà un'istanza allo stesso livello come il percorso MiddleManComponent e così otterrà la stessa istanza di RouteParams. Quando il servizio viene iniettato nel componente del percorso figlio, sarà possibile accedere ai parametri del percorso principale.

Se sono necessarie 2 istanze di EndPointComponent da caricare a livelli di albero di instradamento diversi, credo che sarà necessario un altro livello di percorso principale; cioè un componente indirizzato che incapsula sia MiddleManComponent che EndPointComponent, tra RootComponent.

RootComponent non viene instradato, quindi non sarà possibile istanziare RouteParams per RouteParamService da esso. RouteParams è fornito dal componente <router-outlet>.

+0

Grazie. Questa è una soluzione davvero interessante. Sembra un po 'hacky, vero? Per quanto ne sai, Angular 2 non ha una soluzione integrata per questo? Penserei che il mio caso d'uso è molto comune a meno che l'architettura dei miei componenti non sia concepita male. PS: la soluzione integrata se ne esiste una potrebbe essere in '@ angular/router' piuttosto che la più vecchia' @ angular/router-deprecated' – BeetleJuice

+0

Inizia a sembrare hacky quando si tenta di avere lo stesso componente istanziato su una rotta diversa livelli. Se hai bisogno dei parametri del percorso di livello superiore, in pratica hai bisogno di un componente dedicato solo all'istanziazione del tuo servizio e spingendo gli altri componenti verso il basso di un livello. Questo è uno dei motivi per cui penso che sia un errore di progettazione che i componenti di livello superiore non abbiano accesso a RouteParams. Detto questo, però, l'utilizzo di servizi per condividere dati tra componenti è un modello di progettazione comune per le applicazioni Angular. – awiseman

+0

Mi sento sporco, ma funziona. – BeetleJuice

1

Utilizzo di "@ angular/router": "3.0.0-alpha.6" pacchetto, sono stato in grado di ottenere l'argomento percorso genitore nel modo seguente:

export class ChildComponent { 

    private sub: any; 

    private parentRouteId: number; 

    constructor(
     private router: Router, 
     private route: ActivatedRoute) { 
    } 

    ngOnInit() { 
     this.sub = this.router.routerState.parent(this.route).params.subscribe(params => { 
      this.parentRouteId = +params["id"]; 
     }); 
    } 

    ngOnDestroy() { 
     this.sub.unsubscribe(); 
    } 
} 

In questo esempio il percorso ha il seguente formato: /parent/:id/child/:childid

export const routes: RouterConfig = [ 
    { 
     path: '/parent/:id', 
     component: ParentComponent, 
     children: [ 
      { path: '/child/:childid', component: ChildComponent }] 
    } 
]; 
0

È possibile iniettare ActivatedRote e prendere una snapshot, ancora più facile:

constructor(private route: ActivatedRoute) {}; ngOnInit() { console.log('one of my parents route param:', this.route.snapshot.parent.params['PARAM-NAME']); }

+0

Grazie. La risposta che ho selezionato ha funzionato per me al momento. Angular è cambiato un bel po 'da allora e in realtà ho fatto esattamente quello che suggerisci da quando si è passati a 'rc 4' o' rc 5' – BeetleJuice

3

Utilizzando @angular/[email protected], è possibile accedere al pa affitto ActivatedRoute con

export class ChildComponent implements OnInit { 

    parentRouteId: string; 

    constructor(private route: ActivatedRoute) { 
    } 

    ngOnInit() { 
    this.route.parent.params 
     .subscribe((params: Params) => this.parentRouteId = params['id']); 
    } 
}