I solved this problem like this.
Suppose you have a container news-list.component.ts
with ngOnInit
. It saves current queryParams
in currentFilters
and if there is not them makes simple GET request else it makes POST request.
ngOnInit() {
this.route.queryParams.subscribe(queryParams => {
if (!!queryParams) {
this.currentFilters = <NewsFilter>{...queryParams, offset: 0, size: 6};
this.news$ = this.newsPostsService.getNewsByFilter(this.currentFilters);
} else {
this.news$ = this.newsPostsService.getMainNews();
}
});
}
Then you create an component <news-rubric></news-rubric>
which has following view. You pass there currentFilters
and take rubricClick
which you process next.
news-list.component.html
<ml-news-rubrics [currentFilters]="currentFilters"
(rubricClicked)="onRubricFilter($event)"
></ml-news-rubrics>
news-list.component.ts
onRubricFilter(filters: NewsFilter) {
this.currentFilters = {...filters};
this.router.navigate([], {queryParams: filters, relativeTo: this.route});
}
And then inside news-rubric.component.ts
you do something like this:
onRubricClicked(rubricId: string) {
// check if filter exists and if not then put ID in filter
if (!this.currentFilters.filterByAnyRubricIds) {
this.putIdInFilter('filterByAnyRubricIds', rubricId, this.currentFilters.filterByAnyRubricIds);
} else {
// check if clicked ID is not in filter. put in filter
if (!this.currentFilters.filterByAnyRubricIds.includes(rubricId)) {
this.putIdInFilter('filterByAnyRubricIds', rubricId, this.currentFilters.filterByAnyRubricIds);
} else {
// if ID in filter remove it from filter
this.removeIdFromFilter('filterByAnyRubricIds', rubricId, this.currentFilters.filterByAnyRubricIds);
}
}
this.rubricClicked.emit(this.currentFilters);
}
There is most tricky code. It makes new filter by updating its key with filtered ID.
private putIdInFilter(key: string, value: any, list: any) {
if (!list || !(list instanceof Array)) {
if (!list) {
this.currentFilters = {...this.currentFilters, [key]: [value]};
} else {
this.currentFilters = {...this.currentFilters, [key]: [this.currentFilters[key], value]};
}
} else {
this.currentFilters = {...this.currentFilters, [key]: [...this.currentFilters[key], value]};
}
}
private removeIdFromFilter(key: string, value: any, list: any) {
if (!list || !(list instanceof Array)) {
this.currentFilters = <NewsFilter>{
...this.currentFilters, [key]: null
};
return;
}
const filteredValues = [...list.filter(i => i !== value)];
if (filteredValues.length > 0) {
this.currentFilters = <NewsFilter>{
...this.currentFilters, [key]: filteredValues
};
} else {
delete this.currentFilters[key];
}
}
And NewsFilter
it is merely interface like QueryParams
with keys which are required to be filtered.