Home > Net >  Angular Multiple Filter on Multiple Fields
Angular Multiple Filter on Multiple Fields

Time:07-12

I want to build a filter for a list. The Array of Objects for that looks like this:

myList: [
  {
    "id": 1,
    "title":"title",
    "city":"city name",
    "types":[
      {
        "id":1,
        "name":"type 1 name"
      },
      {
        "id":2,
        "name":"type 2 name"
      }
    ],
    "properties": [
      {
        "id": 1,
        "name": "prop 1 name"
      },
      {
        "id": 2,
        "name": "prop 2 name"
      }
    ]
  },
  {
    "id": 2,
    "title":"title2",
    "city":"city name",
    "types":[
      {
        "id":1,
        "name":"type 1 name"
      }
    ],
    "properties": [
      {
        "id": 2,
        "name": "prop 2 name"
      },
      {
        "id": 3,
        "name": "prop 3 name"
      }
    ]
  },
]

I have select fields with multiple selects on city, type and property.

  <form *ngIf="filterForm" [formGroup]="filterForm">
      <div >
        <div >
          <mat-form-field appearance="outline">
            <mat-label>filter by city</mat-label>
            <mat-select formControlName="filterCity" multiple="true">
              <mat-option *ngFor="let city of cities" [value]="city.name">{{city.name}}</mat-option>
            </mat-select>
          </mat-form-field>
        </div>
        <div >
          <mat-form-field appearance="outline">
            <mat-label>filter by type</mat-label>
            <mat-select  formControlName="filterAdType" multiple="true">
              <mat-option *ngFor="let type of Types" [value]="type.name">{{type.name}}</mat-option>
            </mat-select>
          </mat-form-field>
        </div>
        <div >
          <mat-form-field appearance="outline">
            <mat-label>filter by property</mat-label>
            <mat-select  formControlName="filterProperty" multiple="true">
              <mat-option *ngFor="let prop of Properties" [value]="prop.name">{{prop.name}}</mat-option>
            </mat-select>
          </mat-form-field>
        </div>
      </div>
      <div >
        <div >
          <button mat-button color="primary" (click)='filterSet()'>set filters</button>
        </div>
        <div >
          <button mat-button color="primary" (click)='clearFilters()'>clear filters</button>
        </div>
      </div>
     </form>

and displaying the list in a table

        <table   *ngIf="myList.length > 0">
          <thead>
            <tr>
              <!-- <th scope="col">#</th> -->
              <th scope="col">title</th>
              <th scope="col">type</th>
              <th scope="col">property</th>
              <th scope="col">city</th>
            </tr>
          </thead>
          <tbody>
            <tr *ngFor="let item of myList; let i = index">
              <td>
                <div>
                  <strong>{{item.title}}</strong>
                </div>
              </td>
              <td>
                <div *ngFor="let type of item.types">
                  {{type.name}}
                </div>
              </td>
              <td>
                <div *ngFor="let prop of item.property">
                  {{prop.name}}
                </div>
              </td>
              <td>{{item.city}}</td>
            </tr>
          </tbody>
        </table>

So i am struggling with the filter for the multiple selects, the properties and type array. I want to filter the myList. The filterSet() function is empty at the moment.

CodePudding user response:

First take a backup ( using lodash cloneDeep) of the original values, without any filters, then when the filters are applied, filter the backup array apply it to the array displayed on the HTML.

  filterSet() {
    this.pageList = [];
    this.pageList = this.data.filter((x: any) => {
      const { filterCity, filterAdType, filterProperty } =
        this.filterForm.value;
      return (
        (filterCity && filterCity.length
          ? filterCity.includes(x.city)
          : true) &&
        (filterAdType && filterAdType.length
          ? filterAdType.includes(x.types.name)
          : true) &&
        (filterProperty && filterProperty.length
          ? x.properties.find((item) => filterProperty.includes(item.name))
          : true)
      );
    });
  }

Thanks for providing stackblitz, PFB working example. Issue was that dropdown data names, should match the data in the grid!

stackblitz

  • Related