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

如何获取mat-select的选中对象(无需重新选择)

解决方案

方案1:利用MatSelect内置事件+缓存映射

MatSelect在用户选择时会直接返回选中的选项对象,无需自行遍历数组。对于初始值,提前将数据源转为Map实现快速查找:

代码示例

// 组件内定义
optionsMap = new Map<number, any>();
selectedObject: any;

ngOnInit() {
  // 假设options$是外部传入的Observable数据源
  this.options$.subscribe(options => {
    this.optionsMap.clear();
    options.forEach(opt => this.optionsMap.set(opt.id, opt));
    // 初始化时匹配表单初始ID对应的对象
    const initialId = this.form.get('selectedId')?.value;
    this.selectedObject = this.optionsMap.get(initialId);
  });
}

onSelectionChange(event: MatSelectChange) {
  // 直接从事件中获取选中的完整对象
  this.selectedObject = event.source.selected.viewValue;
}

模板绑定事件:

<mat-select formControlName="selectedId" (selectionChange)="onSelectionChange($event)">
  <mat-option *ngFor="let opt of options$ | async" [value]="opt.id">
    {{ opt.name }}
  </mat-option>
</mat-select>

方案2:封装自定义值访问器组件(复用场景首选)

如果多处需要这种「绑定ID但获取完整对象」的逻辑,封装自定义表单控件,内部处理ID与对象的转换,对外暴露对象、表单存储ID:

核心代码示例

@Component({
  selector: 'app-object-select',
  template: `
    <mat-select [formControl]="innerControl">
      <mat-option *ngFor="let opt of options$ | async" [value]="opt">
        {{ opt.name }}
      </mat-option>
    </mat-select>
  `,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => ObjectSelectComponent),
      multi: true
    }
  ]
})
export class ObjectSelectComponent implements ControlValueAccessor {
  innerControl = new FormControl();
  @Input() options$!: Observable<any[]>;
  private onChangeFn: (id: number) => void = () => {};

  ngOnInit() {
    // 内部控件值变化时,对外输出ID存入父表单
    this.innerControl.valueChanges.subscribe(obj => {
      this.onChangeFn(obj?.id);
    });
  }

  writeValue(id: number): void {
    // 接收父表单的ID值,匹配对应的对象设置到内部控件
    this.options$.pipe(take(1)).subscribe(options => {
      const targetObj = options.find(opt => opt.id === id);
      this.innerControl.setValue(targetObj);
    });
  }

  registerOnChange(fn: any): void {
    this.onChangeFn = fn;
  }

  // 省略registerOnTouched、setDisabledState的标准实现
}

父组件使用:

<app-object-select formControlName="selectedId" [options$]="options$"></app-object-select>
<!-- 可直接通过组件实例获取选中对象,或在组件内部维护对象供展示 -->

方案3:RxJS组合流自动匹配(响应式场景最优)

如果数据源和表单值都是Observable,用RxJS操作符自动关联,无需手动处理初始值与变化:

selectedObject$ = combineLatest([
  // 监听表单ID变化,包含初始值
  this.form.get('selectedId')!.valueChanges.pipe(startWith(this.form.get('selectedId')!.value)),
  this.options$
]).pipe(
  map(([selectedId, options]) => options.find(opt => opt.id === selectedId))
);

模板直接用async管道展示详情:

<div *ngIf="selectedObject$ | async as selectedObj">
  选中项详情:{{ selectedObj.description }} | {{ selectedObj.category }}
</div>

这种方式完全响应式,不管是初始值加载还是用户选择变化,都会自动同步对应的完整对象,无需额外维护状态变量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 13:15:38