I've searched the web (StackOverflow, Rxjs, blogs, etc.) for an answer to my specific case, but I've not found anything for what I'm specifically looking for.
In my Angular component, I have the following:
ngOnInit(): void {
this.activatedRoute.queryParams.subscribe((params: any) => {
if (!!params.page) {
if (params.page <= 1) this.skip = 0;
else this.skip = (params.page - 1) * this.limit;
}
});
this.activatedRoute.params.subscribe((params: any) => {
this.filter = params.filter;
this.term = params.term;
this.year = params.year;
this.month = params.month;
});
this.activatedRoute.data.subscribe((data: any) => {
this.setProvider(data.route);
this.loadData(data.route);
});
}
My problem is I need the queryParams
and the params
subscriptions to complete and assign the public values before the data
subscription takes place (queryParams
and params
can complete in any order as they don't have dependencies on each other).
In all of the examples I've seen, they show where each subscription is dependent on the previous and uses the values of the previous (passed down as variables). If I was using pure functions, I could possibly see where this is beneficial, but given that the code-behind in Angular also functions as a ViewModel, I'm simply setting public variables and then referencing them in the setProvider
and loadData
functions.
The below code works (basically chaining pipes), but given my limited knowledge on all that there is Rxjs, I wasn't sure if there was a cleaner, more efficient way to write this. It seems rather silly to return an observable just to use its values in the next chain of the pipe.
ngOnInit(): void {
this.activatedRoute.queryParams.pipe(concatMap((query: any) => {
if (!!query.page) {
if (query.page <= 1) this.skip = 0;
else this.skip = (query.page - 1) * this.limit;
}
return this.activatedRoute.params;
})).pipe(concatMap((params: any) => {
this.filter = params.filter;
this.term = params.term;
this.year = params.year;
this.month = params.month;
return this.activatedRoute.data;
})).subscribe((data: any) => {
this.setProvider(data.route);
this.loadData(data.route);
});
}
Thanks everyone!
Edit
The below also works using concat
:
ngOnInit(): void {
concat(
this.activatedRoute.queryParams.pipe((q: any) : any => {
let query = q.getValue();
if (!!query.page) {
if (query.page <= 1) this.skip = 0;
else this.skip = (query.page - 1) * this.limit;
}
}),
this.activatedRoute.params.pipe((p: any) : any => {
let params = p.getValue();
this.filter = params.filter;
this.term = params.term;
this.year = params.year;
this.month = params.month;
}),
this.activatedRoute.data.pipe((d: any) : any => {
let data = d.getValue();
this.setProvider(data.route);
this.loadData(data.route);
})
);
}
CodePudding user response:
Thanks to Joosep for the answer. I've updated it due to the his recommended function signature being deprecated.
Here's the updated version:
ngOnInit(): void {
combineLatest([
this.activatedRoute.queryParams,
this.activatedRoute.params,
this.activatedRoute.data,
]).subscribe(
([queryParams, params, data]) => {
if (!!queryParams['page'] && queryParams['page'] <= 1) {
this.skip = 0;
} else {
this.skip = (queryParams['page'] - 1) * this.limit;
}
if (params) {
this.filter = params['filter'];
this.term = params['term'];
this.year = params['year'];
this.month = params['month'];
}
if (queryParams && params && data) {
this.setProvider(data['route']);
this.loadData(data['route']);
}
}
);
}
CodePudding user response:
If it has to be done with manual subscriptions I would combine latest for the activatedRoute queryParams
, params
and data
and with a basic if check run the last part when appropriate.
Something like this maybe:
combineLatest(
this.activatedRoute.queryParams,
this.activatedRoute.params,
this.activatedRoute.data,
(queryParams: Params, params: Params, data: any) => ({
queryParams
params,
data,
})
).subscribe((res: {queryParams: Params; params: Params; data: any }) => {
if (!!queryParams.page && queryParams.page <= 1) {
this.skip = 0;
} else {
this.skip = (queryParams.page - 1) * this.limit;
}
if (params) {
this.filter = params.filter;
this.term = params.term;
this.year = params.year;
this.month = params.month;
}
if (queryParams && params && data) {
this.setProvider(data.route);
this.loadData(data.route);
}
});
Also try to enforce strong types if possible.