问题
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