Angular: Multiple mat-select dropdown with search functionality using mat-select-filter and adding an icon to the filter field

Viewed 8735

I want to implement mat-select-filter in mat-select module. I have added a search icon for searching the items in the dropdown based on characters entered. I have referred this mat-select-filter and stackblitz but I was not getting the filter field.Below is the code that I've used

search-filter.component.html

 <mat-form-field class="input-permissions">
    <mat-select
      placeholder="Permissions"
      multiple
      [formControl]="permissionsControl"
    >
      <mat-select-filter
        [array]="permissions"
        (filteredreturn)="filteredList=$event"
      ></mat-select-filter>
      <mat-option
        *ngFor="let permission of permissions"
        [value]="permission.value"
      >
        {{ permission.value}}
      </mat-option>
    </mat-select>
  </mat-form-field>

mat-select-filter.component.ts

    export class MatSelectFilterComponent{
       permissions: {{id: 0, value: fruit},{id: 1, value: vegetable} };
       public filteredList = this.permissions.slice();
    }

Any help would be appreciated.

1 Answers
  1. permissions needs to be an Array and not an object:

    public permissions = [{id: 0, value: 'fruit' },{id: 1, value: 'vegetable'} ];
    public filteredList = this.permissions.slice();
    
  2. You need to specify the displayMember on mat-select-filter and filteredreturn should be filteredReturn:

    <mat-select-filter [array]="permissions" (filteredReturn)="filteredList=$event" [displayMember]="'value'">
    </mat-select-filter>
    
  3. If using a multiple select you need to do the hiding of the non filtered results yourself. Otherwise you could just iterate over filteredList, but in that case old selections are removed on filtering. Iterate over permissions instead and then hide those, which should not be shown.

    <mat-option *ngFor="let permission of permissions" [value]="permission"
        [class.hide]="!isFiltered(permission)">
        {{permission.value}}
    </mat-option>
    

    and the function for checking the filtered elements

    public isFiltered(permission) {
      return this.filteredList.find(item => item.id === permission.id)
    }
    

    and the css for hiding

    .mat-option.hide {
      display: none;
    }
    
  4. There is no default support for adding some icon to the filter - or at least I didn't find one. Nevertheless you can solve this by using css.

    Add this to your index.html to ensure the font is loaded correctly:

    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    

    Add the following to your css. It adds an ::after element containing the search icon as font. Take care to reduce the width of the input element by the space the icon needs (here it's 20px width and 5px padding-left) to ensure it's placed next to each other.

    .mat-filter-input {
      width: calc(100% - 25px) !important;
    }
    
    .mat-filter::after {
      content: "\e8b6";
      font-family: material icons;
      vertical-align: bottom;
      font-size: 20px;
      padding-left: 5px;
    }
    

    I needed to set the encapsulation: ViewEncapsulation.None within the component, since otherwise the styles had the wrong selector. I'm not sure if this is a stackblitz issue or not. Try it without it. If it works you can also remove !important from the width of the input element.

Here is the link to the solution on stackblitz: https://stackblitz.com/edit/mat-select-filter-zuy7ev

Related