Angular mat-autocomplete 函数返回选项时无法选中的问题
异常产生原因
你当前把选项来源从组件成员变量改为函数返回的实现,触发了MatAutocomplete的内置校验逻辑冲突,直接导致选中失效:
- 原本用组件类成员变量存选项时,数组和数组内每个对象的内存引用在整个组件生命周期内是固定的,选中校验可以正常通过。但改成函数返回选项后,每次Angular变更检测触发
options()函数执行,都会生成一个全新的对象数组——哪怕每个对象的结构、字段值完全一致,数组本身、数组里每个对象的内存引用都是全新的。 - MatAutocomplete组件的选中判定逻辑,对于非基本类型的绑定值,是按内存引用相等做校验的:当你点击某条选项时,组件会把点击时拿到的option对象绑定到表单控件,后续变更检测重新生成选项列表时,新生成的option对象和控件里存的旧对象引用不一致,组件就会判定值不匹配,不会完成选中状态的绑定更新,也就出现了「能看到选项、点了不生效」的现象。
- 选项文本能正常渲染,是因为渲染阶段只需要读取对象的
value字段拼接展示内容,不需要做引用相等校验,所以完全不受这个问题影响。
可落地的修复方案
- 方案一:给函数返回的结果增加引用缓存,保证多次调用返回的是同一个数组实例
不要每次执行函数都重新生成数组,把生成的数组存在组件的私有变量里,首次执行时生成、后续直接返回缓存的实例,从根源上保证对象引用稳定。示例代码:export class AutocompleteSimpleExample { myControl = new FormControl(); // 新增私有缓存变量 private _optionCache: KeyValue[] | null = null; options(): KeyValue[] { // 缓存存在则直接返回,不生成新实例 if (!this._optionCache) { this._optionCache = [{ key: "1", value: "One" }]; } return this._optionCache; } } - 方案二:调整
mat-option的绑定值为基本类型,绕开引用对比逻辑
把原本绑定整个option对象的逻辑,改成绑定对象里的字符串字段(比如key值)。基本类型的相等校验是按值判断的,哪怕每次函数返回新的对象实例,只要key值一致,选中校验就能正常通过。如果需要在输入框展示可读的value文本,配合displayWith做值到展示文本的映射即可。示例模板代码:
对应的组件类补充映射方法:<mat-autocomplete #auto="matAutocomplete"> <mat-option *ngFor="let option of options()" [value]="option.key"> {{option.value}} </mat-option> </mat-autocomplete>
记得给关联的输入元素补上// 值到展示文本的映射 displayOptionText = (key: string) => { const matched = this.options().find(item => item.key === key); return matched ? matched.value : ''; }[displayWith]="displayOptionText"的绑定,避免选中后输入框直接显示key字符串。
内容的提问来源于stack exchange,提问作者Alex Burtsev
相关产品推荐
相关产品推荐

