mat-select multiple实现搜索筛选时多次选中仅保留最后一项问题求助
问题根因
Angular mat-select 多选模式下,仅当mat-option实际渲染在DOM中时,对应的选中值才会被保留在绑定的ngModel/FormControl中。
你的实现中每次搜索都会直接替换用来渲染mat-option的数组,之前选中但不在本次搜索结果里的选项对应的mat-option会被直接销毁,mat-select会自动将这些不存在的选项从选中列表中移除,最终仅保留最后一次搜索时选中的项。
修复方案
1. 拆分数据变量
将全量原始数据、搜索过滤后的展示数据、选中数据拆分为三个独立变量,避免搜索操作影响已选中的值和全量数据。
2. 新增面板关闭重置逻辑
监听mat-select的关闭事件,面板关闭时清空搜索关键词、重置展示列表为全量数据,保证所有已选中项都有对应的mat-option存在。
3. 修正值匹配逻辑
保持mat-option的value绑定和ngModel存储的选中值格式一致,避免值匹配失败导致的选中项丢失。
完整修改代码
TS代码
// 全量原始分类数据,永不修改 categories: any[] = []; // 搜索过滤后的展示列表,仅用于渲染mat-option filteredCategories: any[] = []; // 选中的分类列表,与ngModel绑定 testCategories: any[] = []; // 搜索关键词 filter: string = ''; // 可选:绑定搜索输入框的模板引用,用于清空输入内容 @ViewChild('searchInput') searchInput: MatInput; ngOnInit() { // 初始化时展示全量分类 this.filteredCategories = [...this.categories]; } onKey(value: string) { this.filter = value.toLowerCase(); // 仅修改过滤展示列表,不影响全量数据和选中数据 this.filteredCategories = this.categories.filter(option => option.name.toLowerCase().startsWith(this.filter) ); } // 面板关闭时触发,重置搜索状态 onPanelClosed() { this.filter = ''; this.filteredCategories = [...this.categories]; // 清空搜索输入框内容 if(this.searchInput) { this.searchInput.value = ''; } } // 可选:如果mat-option绑定的是id而非完整对象,需添加compareWith函数匹配值 compareFn(id1: number, id2: number): boolean { return id1 === id2; } // 你的原有移除分类逻辑 removeCategory(category: any) { this.testCategories = this.testCategories.filter(item => item.id !== category.id); }
HTML代码
<mat-select formControlName="testCategories" [(ngModel)]="testCategories" multiple (closed)="onPanelClosed()" <!-- 可选:如果绑定的是id,添加compareWith --> <!-- [compareWith]="compareFn" --> > <input #searchInput matInput class="search-input" type="text" placeholder="Search..." (keyup)="onKey($event.target.value)" (keydown)="$event.stopPropagation()" > <mat-select-trigger> <mat-chip-list> <mat-chip *ngFor="let category of testCategories" [removable]="true" (removed)="removeCategory(category)" > <div class="chip-text">{{ category.name }}</div> <mat-icon class="icon-delete-circle-reverse" matChipRemove></mat-icon> </mat-chip> </mat-chip-list> </mat-select-trigger> <ng-container *ngFor="let category of filteredCategories"> <mat-option <!-- 如果存储的是完整分类对象,绑定category,否则绑定category.id --> [value]="category" > {{ category.name }} </mat-option> </ng-container> </mat-select>
内容的提问来源于stack exchange,提问作者akromx
相关产品推荐
相关产品推荐

