web-dev-qa-db-fra.com

Abonnez-vous aux paramètres de route et à queryParams dans Angular 2

J'ai mis en place le système de routage suivant

export const MyRoutes: Routes = [
    {path: '', redirectTo: 'new', pathMatch: 'full'},
    {path: ':type', component: MyComponent}
];

et avoir le système de navigation suivant

goToPage('new');
goToPageNo('new', 2);

goToPage(type) {
    this.router.navigate([type]);
}
goToPageNo(type, pageNo) {
    this.router.navigate([type], {queryParams: {page: pageNo}});
}

Exemple URL ressemble à ceci

http: // localhost: 3000/new

http: // localhost: 3000/new? page = 2

http: // localhost: 3000/updated

http: // localhost: 3000/updated? page = 5

Parfois ils ont optional queryParams (page)

Maintenant, je dois lire les paramètres route et queryParams

ngOnInit(): void {
    this.paramsSubscription = this.route.params.subscribe((param: any) => {
        this.type = param['type'];
        this.querySubscription = this.route.queryParams.subscribe((queryParam: any) => {
            this.page = queryParam['page'];
            if (this.page)
                this.goToPageNo(this.type, this.page);
            else
                this.goToPage(this.type);
        });
    });
}

ngOnDestroy(): void {
    this.paramsSubscription.unsubscribe();
    this.querySubscription.unsubscribe();
}

Maintenant, cela ne fonctionne pas comme prévu, visiter des pages sans que queryParams fonctionne, puis je visite une page avec queryParams "goToPageNo" étant appelé plusieurs fois, car je m'abonne à queryParams dans les paramètres de route.

J'ai regardé la documentation Angular 2, ils n'ont aucun exemple ou code où un abonnement à both route params et queryParams est implémenté en même temps. 

Un moyen de le faire correctement? Aucune suggestion?

18
ThunderRoid

Pour angulaire 6+

import { combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';

...

combineLatest(this.route.params, this.route.queryParams)
    .pipe(map(results => ({params: results[0].xxx, query: results[1]})))
    .subscribe(results => {
        console.log(results);
    });

xxx est de votre route

{path: 'post/:xxx', component: MyComponent},

8
ThunderRoid

J'ai réussi à obtenir un seul abonnement à la fois à queryParams et à Params en combinant les observables à l'aide de Observable.combineLatest avant de m'abonner.

Par exemple.

var obsComb = Observable.combineLatest(this.route.params, this.route.queryParams, 
  (params, qparams) => ({ params, qparams }));

obsComb.subscribe( ap => {
  console.log(ap.params['type']);
  console.log(ap.qparams['page']);
});
39
pblack

Réponse tardive, mais une autre solution: Au lieu de souscrire aux paramètres et queryparams, je souscris à l'événement NavigationEnd sur le routeur. Ne se déclenche qu'une seule fois et les paramètres et queryparams sont disponibles dans l'instantané: (exemple pour Angular 4)

this.router.events.filter(event=>event instanceof NavigationEnd)
   .subscribe(event=>{
       let yourparameter = this.activatedroute.snapshot.params.yourparameter;
       let yourqueryparameter = this.activatedroute.snapshot.queryParams.yourqueryparameter;
   });

En ce qui concerne la désinscription: oui, il est vrai que les paramètres de routage, queryParams ou les événements de navigation sont automatiquement désabonnés par le routeur. Il existe toutefois une exception: si votre route a des enfants, lors de la navigation entre les enfants, aucune désinscription ne sera effectuée. Seulement lorsque vous quittez la route parente!

Par exemple. J'ai eu une situation avec des onglets comme itinéraires enfants. Dans le constructeur du premier composant onglet s'abonner sur route param pour récupérer les données. Chaque fois que je navigue du premier au deuxième onglet et retour, un autre abonnement a été ajouté, ce qui a multiplié le nombre de demandes.

8
rekna

Utilisez ActivatedRouteSnapshot de votre ActivatedRoute

ActivatedRouteSnapshot interface a les propriétés params et queryParams et vous pouvez obtenir les deux valeurs en même temps.

constructor(private route: ActivatedRoute) {
    console.log(this.route.snapshot.params);
    console.log(this.route.snapshot.queryParams);
}

Edit: Comme indiqué par OP, nous n’obtenons que la valeur initiale des paramètres avec cette technique.

Exemple Plunker

1
Michael