Display Unique values of mat-select that gets data from Angular filtered dataSource

2.3k Views Asked by At

I'm doing an app with Angular 9. This app displays data based on a mat-table but the data it's filtered by some fields, something like that:

Example of dropdown filtering for the table

The problem is that the dropdown displays repetead values (it's normal because for example a Country can be repeated in some rows), and the data that is displayed it's based on a mat-table dataSource.filteredData so I cannot do a new Set() or similar. And I'm asking myself how to change/modify my code to display only unique values on the dropdown.

My code is similar to this:

<mat-form-field appearance="fill">
    <mat-label>Select an option</mat-label>
    <mat-select>
        <mat-option *ngFor="let country of dataSource.filteredData">{{country.name}}</mat-option>
    </mat-select>
</mat-form-field>

...

<table>
...
</table>

psd: I tried to do a Pipe for unique, but this only works (properly) for statick Arrays and my Array changes depending on the filter.

Any suggestions? Thanks for your help

2

There are 2 best solutions below

0
On BEST ANSWER

I found a solution that it works, basically I refactored the ngFor code and created a function that returns an array with no repeated values.

first of all I created the function that return the non-repeated array:

//Basically this method only needs the name of the field/key you are searching
nonRepeated(field: string): string[] {
//First we create the array that we want to return transformed
    let arrayField = [];
//We iterate over our filteredData
    for (let item of this.dataSource.filteredData) {
//We push the value of the field to our previous array
      arrayField.push(item[field]);
    }
//Here we sort the Array alphabetically
    arrayField = arrayField.sort();
//Finally we return the array with non-repeated values thanks to ES6 ❤
    return [...new Set(arrayField)];
  }

Additional infor for Set ES6: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set

Refactored ngFor

<mat-form-field appearance="fill">
    <mat-label>Select an option</mat-label>
    <mat-select>
        <mat-option *ngFor="let country of nonRepeated('country')">{{country}}</mat-option>
    </mat-select>
</mat-form-field>
1
On

Use below ES6 feature

this.arr=this.arr.filter((val,ind,arr)=>arr.indexOf(val)===ind)