2

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.

3 Answers 3

4

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.

1
  • 1
    Having seen number of overly complex and verbose solutions elsewhere on the StackOverflow, I reckon this is simple yet effective solution.
    – Ali Celebi
    Commented Jan 16, 2023 at 17:13
2

Thanks to everyone who has contributed to this thread so far. I found the solutions provided to be helpful, but I encountered a couple of issues that I wasn't able to resolve.

The first issue was that I couldn't search for options that contained spaces. When I tried to enter a space in the search input, it would trigger the selection or deselection of options instead. This made it difficult to find specific options that contained spaces in their names.

The second issue was that if I selected an option and then changed the search input, any previously selected options that didn't match the search criteria would be deselected. This was problematic because it meant that I had to reselect the options every time I changed the search input.

After some experimentation, I was able to come up with a solution that resolved these issues

You can see this solution in action in this StackBlitz example

I hope this helps anyone else who might have encountered similar issues. Thanks again to everyone who contributed to this thread!

0

Thank you. I also had the problem with the space bar and event.stopPropagation() did the trick.

In my implementation the relevant part to focus the search field on dropdown opening and keep the focus when adding a space into the search field is this:

typescript:

  focusSearchField(event: any) {
    this.searchInput.nativeElement.focus();
    // prevent space in search field ticking the checkbox instead of typing a space
    if (event?.code === 'Space') { event.stopPropagation(); } 
  }

html:

<mat-form-field>
    <mat-select formControlName="fcMulti" multiple
        (openedChange)="focusSearchField($event)"
        (selectionChange)="onSelection($event.value)">
        ....
            <div fxFlex="60%" class="search-input">
                <input #searchInput type="text" matInput (keydown.space)="focusSearchField($event)" (keyup)="applyFilter($event.target.value)">
            </div>
            ....

Not the answer you're looking for? Browse other questions tagged or ask your own question.