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

Angular mat-select动态增删mat-option后选中值空白失效问题

Angular Material Select 新增对象后选中空白问题排查与解决

问题背景

我正在开发一个支持对象增删的步进器组件,使用mat-select作为选择器。预期逻辑为:新增医生时,医生对象会被追加到options数组,组件绑定值同步更新,选择器自动切换到刚新增的对象。

实际运行时问题如下:绑定到选择器的选中选项、默认值已发生变更,但选择器会取消原有选中值,且不会重新选中任何选项,始终处于空白状态,所有按此逻辑构建的组件都出现相同问题。

相关代码

选择器HTML代码

<mat-form-field
  class="form-field"
  ngDefaultControl
  [appearance]="appearance"
  [formControl]="formControl">
  <mat-label>
    Doktor
  </mat-label>
  <mat-select ngDefaultControl [(value)]="defaultValue" [compareWith]="compare">
    <mat-option *ngFor="let doctor of options" [value]="doctor" (onSelectionChange)="handleSelectionChange($event, doctor)">{{"Doktor " + (options.indexOf(doctor) + 1)}}</mat-option>
  </mat-select>
</mat-form-field>

动态表单HTML代码

<div *ngIf="options.length > 0; else listIsEmpty">
  <div *ngFor="let doctor of options" class="filter-view-complete-wrapper">
    <div [hidden]="doctor != selectedOption" class="filter-view-each-wrapper">
      <mat-divider class="form-field"></mat-divider>
      <div class="filter-view-form-wrapper">
        <km-doctor-form
          [formComponent]="formComponent"
          [buttonsEnabled]="false"
          [doctor]="doctor"
          (valueChanged)="emitObject($event)"
          [stepperMode]="true"
          [readOnly]="false">
        </km-doctor-form>
      </div>
      <button
        mat-raised-button
        color="primary"
        (click)="removeDoctor(doctor)">
        <mat-icon>
          remove
        </mat-icon>
        {{'kita-manager.information-adjustment.remove-doctor' | translate}}
      </button>
      <mat-divider class="form-field"></mat-divider>
    </div>
  </div>
</div>

初始化值选择逻辑

ngOnInit(): void {
  this.options = this.occupancies.map(occupancy => occupancy?.child.doctor).filter(item => !!item);
  this.defaultValue = this.options[0];
  this.selectedOption = this.defaultValue;
  this.removeDuplicateDoctors();
  this.setupFilter();
}

对象增删逻辑

// selectOption方法仅负责设置this.selectedOption的值
addDoctor() {
  this.options.push({} as DoctorShowDto);
  const value = this.options[this.options.length - 1];
  this.defaultValue = value;
  this.selectOption(value);
}

removeDoctor(doctor: DoctorShowDto) {
  const index = this.options.indexOf(doctor);
  this.options.splice(index, 1);
  const value = this.options[index - 1];
  this.defaultValue = value;
  this.selectOption(value);
}

排查过程

我曾尝试通过ViewChild获取MatSelect实例,调用writeValue等方法或直接赋值,和值绑定的逻辑效果一致,始终无法生效。
后续发现问题仅出现在新增的空对象上,组件初始化时就存在的对象选中逻辑完全正常,因此怀疑问题出在compareWith绑定的对比函数上。

解决方案

经过排查确认,问题确实出在基于id的对比函数上:前端临时创建的空对象没有id字段,原有对比函数始终返回不匹配,导致选择器找不到对应选中项。
我重新实现了compareByName对比函数,通过姓名字段做对象匹配,替换原有基于id的对比逻辑后,选择器选中功能恢复正常。


内容的提问来源于stack exchange,提问作者cmedi32

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 20:24:02