angulardrop-down-menuangular-materialangular11

How to implement search functionality in multi select drop down of angular material


I am working on a project where I need to implement search with multi select drop down. When I added below code, I am able to search but my previously selected value is disappearing after new search.

Below is the code snippet.

HTML:

<mat-form-field appearance="fill">
    <mat-label>Providers</mat-label>
    <mat-select  multiple [formControl]="providers">
      <mat-select-trigger>
        {{providers.value  }}
      </mat-select-trigger>
      <input type="text"  autocomplete="off" matInput placeholder="Search By Provider" #multiUserSearch ( 
 input)="onInputChange()">
     
      <mat-option *ngFor="let provider of provider " [value]="provider.PROV">{{provider.PROV}} 
</mat-option>
</mat-select>
 

TS FILE:

onInputChange(){
        console.log(this.multiUserSearchInput.nativeElement.value);
        const searchInput=this.multiUserSearchInput.nativeElement.value?
        this.multiUserSearchInput.nativeElement.value.toLowerCase():'';
        
          this.provider=this._provider.filter(u=>{
            const PROV:string=u.PROV.toLowerCase().;
            return PROV.indexOf(searchInput) > -1;
          });           
      
      } 

Can you please help me.


Solution

  • Since you're using a filtered list to provide the value to the dropdown, once that filtered list no longer contains the value, it resets.

    Using your code, you should probably go with something like:

    HTML:

    <mat-form-field appearance="fill">
      <mat-label>Providers</mat-label>
      <mat-select multiple [formControl]="providers" (openedChange)="onOpenChange(multiUserSearch)">
        <mat-select-trigger>
          {{providers.value }}
        </mat-select-trigger>
        <input #multiUserSearch type="text" autocomplete="off" matInput placeholder="Search By Provider" (input)="onInputChange($event)"/>
    
        <mat-option *ngFor="let provider of filteredProviders" [value]="provider.PROV">{{provider.PROV}}</mat-option>
      </mat-select>
    </mat-form-field>
    

    Component:

    export class SelectMultipleExample {
      providers = new FormControl();
      allProviders: any[] = [{ PROV: "aaa" }, { PROV: "aab" }, { PROV: "aac" }];
      filteredProviders: any[] = this.allProviders;
    
      onInputChange(event: any) {
        const searchInput = event.target.value.toLowerCase();
    
        this.filteredProviders = this.allProviders.filter(({ PROV }) => {
          const prov = PROV.toLowerCase();
          return prov.includes(searchInput);
        });
      }
    
      onOpenChange(searchInput: any) {
        searchInput.value = "";
        this.filteredProviders = this.allProviders;
      }
    }
    

    Stackblitz Demo

    That said, not sure I'd implement such functionality myself as there are many edge cases here. you should probably use an existing library to do so.