If you're building Angular apps using Angular Material, chances are you're using mat-select
for dropdowns. But when you combine multiple
selection with custom search functionality, an odd bug appears: selecting values after searching can cause earlier selections to disappear. Here's why that happens — and how to fix it.
The Problem
Imagine this flow:
- You search for “Cal”, select California
- You clear the search
- Then search for “Ala”, select Alabama
- Suddenly, California disappears from your selection. ❌
This issue occurs because mat-select
only keeps track of what's in the current dropdown list. When you filter options and omit already-selected values, Angular can't track them anymore — they vanish.
The Solution
To fix this, we need to ensure selected values always remain in the filtered list, even if they don’t match the search.
HTML CODE
<mat-form-field appearance="fill">
<mat-label>Select a state</mat-label>
<mat-select [(value)]="selectedStates" [multiple]="true" (openedChange)="onDropdownOpen($event)">
<mat-option>
<input
matInput
placeholder="Search..."
[(ngModel)]="searchText"
(keyup)="filterStates()"
(click)="$event.stopPropagation()" />
</mat-option>
<mat-option *ngFor="let state of filteredStates" [value]="state">
{{ state }}
</mat-option>
</mat-select>
</mat-form-field>
TS CODE
selectedStates: string[] = [];
searchText: string = '';
states: string[] = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado'];
filteredStates: string[] = [...this.states];
filterStates() {
const search = this.searchText.toLowerCase();
const filtered = this.states.filter(state =>
state.toLowerCase().includes(search)
);
this.filteredStates = [...new Set([...filtered, ...this.selectedStates])];
}
onDropdownOpen(opened: boolean) {
if (opened) {
this.searchText = '';
this.filteredStates = [...new Set([...this.states, ...this.selectedStates])];
}
}
✅ Done!
With this fix, selected options are always retained — no matter what you're searching.
mat-select
only keeps track of what's in the current dropdown list. When you filter options and omit already-selected values, Angular can't track them anymore — they vanish.
HTML CODE
<mat-form-field appearance="fill"> <mat-label>Select a state</mat-label> <mat-select [(value)]="selectedStates" [multiple]="true" (openedChange)="onDropdownOpen($event)"> <mat-option> <input matInput placeholder="Search..." [(ngModel)]="searchText" (keyup)="filterStates()" (click)="$event.stopPropagation()" /> </mat-option> <mat-option *ngFor="let state of filteredStates" [value]="state"> {{ state }} </mat-option> </mat-select> </mat-form-field>
TS CODE
selectedStates: string[] = []; searchText: string = ''; states: string[] = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado']; filteredStates: string[] = [...this.states]; filterStates() { const search = this.searchText.toLowerCase(); const filtered = this.states.filter(state => state.toLowerCase().includes(search) ); this.filteredStates = [...new Set([...filtered, ...this.selectedStates])]; } onDropdownOpen(opened: boolean) { if (opened) { this.searchText = ''; this.filteredStates = [...new Set([...this.states, ...this.selectedStates])]; } }
With this fix, selected options are always retained — no matter what you're searching.