Angular5中mat-selection-list搜索后选中状态丢失问题求助
Hey, I’ve run into this exact issue before with Angular Material’s selection list and filtering! The problem here is that when you filter the list and then clear the search, the component renders brand new instances of your list items. Since Angular Material tracks selected items by object reference, the "new" items don’t match the ones you originally selected, so it automatically deselects them.
Here’s how to fix it by tracking selections with unique identifiers instead of object references:
Step 1: Track selected items by their unique ID
Instead of storing the selected objects directly, store their unique IDs (like an id property, or even the name if you’re sure it’s unique). This way, we don’t rely on object references to determine what’s selected.
In your component class:
// Assume your list items have an `id` property (add one if they don't!) selectedItemIds: number[] = []; // Keep a copy of the original, unfiltered list originalItems = [ { id: 1, name: 'Sneakers' }, { id: 2, name: 'Moccasins' }, { id: 3, name: 'Loafers' }, { id: 4, name: 'Clogs' }, // ... your other list items ]; filteredItems = [...this.originalItems];
Step 2: Update your filtering logic
Make sure you always filter from the original list, not the filtered one—this prevents accidental data loss or skewed results:
applyFilter(searchTerm: string) { if (!searchTerm.trim()) { this.filteredItems = [...this.originalItems]; return; } this.filteredItems = this.originalItems.filter(item => item.name.toLowerCase().includes(searchTerm.toLowerCase()) ); }
Step 3: Modify the template to use ID-based selection
Instead of letting mat-selection-list handle selection state automatically, explicitly set the [selected] property based on whether the item’s ID is in your selectedItemIds array. Also update the selection change handler to manage the ID array:
<!-- Search input --> <input type="text" (input)="applyFilter($event.target.value)" placeholder="Search..."> <!-- Selection list --> <mat-selection-list (selectionChange)="onSelectionChanged($event)"> <mat-list-option *ngFor="let item of filteredItems" [value]="item" [selected]="selectedItemIds.includes(item.id)" > {{ item.name }} </mat-list-option> </mat-selection-list>
Step 4: Update the selection change handler
Modify the handler to add/remove IDs from the selectedItemIds array instead of storing objects:
onSelectionChanged(event: MatSelectionListChange) { const itemId = event.option.value.id; if (event.option.selected) { this.selectedItemIds.push(itemId); } else { this.selectedItemIds = this.selectedItemIds.filter(id => id !== itemId); } }
Why this works
By using unique IDs instead of object references, we decouple the selection state from the rendered list items. Even when the list re-renders after filtering, Angular checks if each item’s ID is in the selectedItemIds array—if it is, the item stays selected, regardless of whether it’s a new object instance from the filtering process.
If your list items don’t have an id property, you can use the name (assuming names are unique) or generate a unique identifier for each item when initializing the list.
内容的提问来源于stack exchange,提问作者Anil Arya

