You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 04:36:04