Subscribe to both route params and queryParams in Angular 2

那年仲夏 提交于 2019-12-17 22:45:11

问题


I have set up the following routing system

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

and have the following navigation system

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

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

Sample URL looks like this

http://localhost:3000/new

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

http://localhost:3000/updated

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

Sometimes they have optional queryParams (page)

Now I need to read both route params and 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();
}

Now this is not working as expected, visiting pages without queryParams works, then of I visit a page with queryParams "goToPageNo" gets called multiple times, as I am subscribing to queryParams inside route params.

I looked at the Angular 2 documentation, they do not have any example or codes where a subscription to both route params and queryParams is implemented at the same time.

Any way to do this properly? Any suggestions?


回答1:


I managed to get a single subscription to both the queryParams and Params by combining the observables by using Observable.combineLatest before subscribing.

Eg.

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']);
});



回答2:


For Angular 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);
    });

Where xxx is from your route

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




回答3:


Late answer, but another solution : Instead of subscribing to the params and queryparams I subscribe to the NavigationEnd event on the router. Fires only once and both params and queryparams are available on snapshot : (example for 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;
   });

Regarding unsubscribing : yes it is true routing params, queryParams or navigation events subscriptions are automatically unsubscribed by the router, there is however one exception : if your route has children , when navigating between children, no unsubscribe will occur. Only when you navigate away from the parent route!

E.g. I had a situation with tabs as child routes. In constructor of first tab component subscribing on route params to retrieve data. Each time I navigate from first to second tab and back another subscription was added resulting in multiplying the number of requests.




回答4:


Use ActivatedRouteSnapshot from your ActivatedRoute

ActivatedRouteSnapshot interface has params and queryParams property, and you could get the both value at the same time.

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

Edit : As OP stated, we only get the initial value of the parameters with this technique.

Example Plunker




回答5:


I think you should use zip operator https://www.learnrxjs.io/operators/combination/zip.html

Because if you use combineLatest and change url params or query params you got value with new query params and old url params.

Urls for example:

http://localhost/1?value=10

http://localhost/2?value=20

http://localhost/3?value=30




回答6:


An alternative (on Angular 7+) is to subscribe to the ActivatedRoute url observable and use "withLatestFrom" to get the latest paramsMap and queryParamsMap. It appears that the params are set before the url observable emits:

this.route.url.pipe(
  withLatestFrom(this.route.paramMap, this.route.queryParamMap)
).subscribe(([url, paramMap, queryParamMap]) => {
  // Do something with url, paramsMap and queryParamsMap
});

https://rxjs-dev.firebaseapp.com/api/operators/withLatestFrom

https://angular.io/api/router/ActivatedRoute



来源:https://stackoverflow.com/questions/40699229/subscribe-to-both-route-params-and-queryparams-in-angular-2

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!