0
votes

I am trying to implement data filtering in my Angular application. The general idea is that the user makes his selection of filters from the drop-down fields and clicks a button that appends the key-value pairs of filters to the route.

I have 2 drop-down fields for filtering data.

<!-- CHOOSE ENTITY TYPE DROPDOWN -->
<div class="row mt-3 text-center">
    <div class="col">
        <mat-form-field>
            <mat-label>Entity Type</mat-label>
            <mat-select
                [formControl]="filterEntityType"
                multiple
            >
                <mat-option
                    *ngFor="let option of entityTypes"
                    [value]="option"
                >
                    {{ option }}
                </mat-option>
            </mat-select>
        </mat-form-field>
    </div>
</div>

<!-- CHOOSE PUBLISHER DROPDOWN -->
<div class="row text-center">
    <div class="col">
        <mat-form-field>
            <mat-label>Publisher</mat-label>
            <mat-select
                [formControl]="filterPublisher"
                multiple
            >
                <mat-option
                    *ngFor="let option of publishers"
                    [value]="option"
                >
                    {{ option }}
                </mat-option>
            </mat-select>
        </mat-form-field>
    </div>
</div>                    

The user makes his selection, which can be multiple and clicks the Apply button.

<button
    type="button"
    class="btn btn-primary btn-lg m-1"
    (click)="applyFilters()"
>
    Apply
</button>

After clicking the button, the following method gets executed

applyFilters() {
    let appliedFilters: Params = [];

    if (this.filterEntityType.value && this.filterEntityType.touched) {
        this.filterEntityType.value.forEach(element => {
            appliedFilters.push({ ["type"]: element });
        });
    }
    if (this.filterPublisher.value && this.filterPublisher.touched) {
        this.filterPublisher.value.forEach(element => {
            appliedFilters.push({ ["publisher"]: element });
        });
    }
    this.router.navigate(["/workspace"], {
        queryParams: appliedFilters,
        relativeTo: this.route
    });
}

As you can see, I am trying to create a local variable appliedFilters of type Params and push key-value pairs inside it, depending on the selected filters. After that, I simply pass the appliedFilters to queryParams from the router's NavigationExtras.

The default URL(when no filters are selected) of the component is /sample/workspace. After selecting the fiters, I would like to have a URL that looks something like this /sample/workspace?type=footype1&type=footype2&publisher=foopublisher.

The type repeats because multiple filter selection is accepted.

Howerver, it seems that the router can not read the key-value pairs and displays Object instead. Thus, I end up with the following URL /sample/workspace?0=%5Bobject%20Object%5D&1=%5Bobject%20Object%5D&2=%5Bobject%20Object%5D.

1

1 Answers

0
votes

When multiple values of same key are to be passed, send them as comma seperated. Also pass JSON object istead of array as queryparams.

applyFilters() {
    let appliedFilters = {};

    if (this.filterEntityType.value && this.filterEntityType.touched) 
        appliedFilters["type"]  = this.filterEntityType.value.toString();

    if (this.filterPublisher.value && this.filterPublisher.touched) 
        appliedFilters["publisher"] = this.filterPublisher.value.toString();

    this.router.navigate(["/workspace"], {
        queryParams: appliedFilters,
        relativeTo: this.route
    });
}