Rohit Soni
Rohit Soni

Reputation: 57

Adding search functionality in mat-multiple select in angular material

I want to add search functionality in my mat multiple select dropdown. I have done this thing in Jquery but I want to do same thing in Angular material. Here is the design pic. Here is the image

Upvotes: 1

Views: 25986

Answers (4)

Kyrolus Kamal Fahim Sous
Kyrolus Kamal Fahim Sous

Reputation: 1018

My approach for this solution is as follow: I populated mat-option from an array of object with many parameters. Of course, I used only one or 2 parameters to show, but I want my user to search by any value of the object even the values of the parameters that are not shown in the mat-option, So, in the template I created an input field like the follow

  <mat-form-field>
    <mat-select multiple>

        <input matInput placeholer="Search" (input)="search($event)" />
      <mat-option *ngFor="let d of data" [value]="d">
        {{d}}
      </mat-option>
    
    
    </mat-select> 
 </mat-form-field>

And in the .ts file:

AllData:any[]; //of course the type will be the type of your data.

Search(event: any, PropertyToSearch: string)
  {
    this.data = this.AllData.filter(x =>
    {
      for (let v of String(event.target.value).trim().split(" "))
      {
        if (Object.values(x).join(" ").toLowerCase().includes(v.toLowerCase()))
          return true;
      }
      return false;
    });
  }

In this function, I creates an array of the words entered by the user, and joined all the values of the each object inside the data array and search each word inside that joined string. Why did I do that? Because there is a case when the user by mistake add 2 spaces between 2 words like this "word1 word2".

If I used simple solution like

this.AllData.filter(x => x.toLowerCase().includes(event.target.value.toLowerCase()));

and the user write the words with only one space between the words, the matched result will not shown. Also, my solution make the user use any value he remember to search with.

Upvotes: 0

dasunse
dasunse

Reputation: 3079

Try this example in stackblitz

stackblitz example with angular 8

in your html file

 <h2>Multiple selection</h2>
  <p>
    <mat-form-field>
      <mat-select [formControl]="bankMultiCtrl" placeholder="Banks" [multiple]="true">
        <mat-select-search [formControl]="bankMultiFilterCtrl"></mat-select-search>
        <mat-option *ngFor="let bank of filteredBanksMulti | async" [value]="bank">
          {{bank.name}}
        </mat-option>
      </mat-select>
    </mat-form-field>
  </p>
  <p>
    Selected Banks: 
  </p>
  <ul *ngFor="let bank of bankMultiCtrl?.value">
    <li>{{bank.name}}</li>
  </ul>

Upvotes: 9

user12337344
user12337344

Reputation:

Instead of using a mat-select, use a mat-autocomplete. https://material.angular.io/components/autocomplete/overview

You can make it work the same as a mat-select by populating it with all values when the input is blank, then filter the auto-complete options when the input value changes.

Again, the trick is to make it show all available options when the input is empty.

Hope this helps.

Edit:

I should add that I use a mat-chip-list (https://material.angular.io/components/chips/overview) for the multi-select part of the equation. When an option is selected, add it to the chip list, and you can add X icons to each chip to remove things from the list.

Granted, this is my personal flavor of a multi-select input, but I thought it might give you some ideas.

Upvotes: 0

Havald
Havald

Reputation: 731

The problem is that the material select doesn't have the functionality for an input. Therefore you need to do a bit of css to make it look good.

<mat-select multiple>

  <mat-form-field>
    <input matInput placeholer="Search" (input)="filterOptione($event.target.value)" />
  </mat-form-field>

  <mat-option *ngFor="let option of options" [value]="option">
    {{option}}
  </mat-option>


</mat-select> 

The filter function:

public filterOptions(filter: string): void {
 this.options = this._unfilteredOptions.filter(x => x.toLowerCase().includes(filter.toLowerCase()));
}

Upvotes: 6

Related Questions