Angular Material中mat-chip无法根据FormControl初始值渲染的问题
解决Angular Material多选Select初始值Mat-Chip不渲染的问题
我帮你排查了下代码,发现几个关键问题导致初始值的mat-chip没正常渲染,咱们一步步来解决:
问题根源
- 对象引用不匹配:你初始化FormControl用的是
[{ id: 1, name: "Extra cheese" }],这是一个全新的对象;而5秒后异步加载的toppingList$里的{ id: 1, name: "Extra cheese" }是另一个不同引用的对象。Angular Material的多选mat-select默认用对象引用相等来匹配选中项,所以即使内容一样,也不会被识别为有效选中项,进而影响trigger里chip的渲染。 - 变更检测时机:初始时
toppingList$还没返回数据,mat-select没有可选项,这时候mat-select-trigger的内容可能不会被正确触发渲染,哪怕FormControl已经有值。 - 类型错误:
onToppingRemoved方法里错误地把对象数组当成字符串数组处理,这会导致移除功能失效,后续操作也会出问题。
修复后的代码
TS代码
import { Component, OnInit } from '@angular/core'; import { FormControl } from '@angular/forms'; import { Subject } from 'rxjs'; export class SelectMultipleExample implements OnInit { private test = new Subject<{ id: number; name: string }[]>(); toppingList$ = this.test.asObservable(); toppingsControl = new FormControl<{ id: number; name: string }[]>([]); // 明确类型 constructor() {} ngOnInit(): void { // 模拟异步加载选项 setTimeout(() => { const toppingList = [ { id: 1, name: "Extra cheese" }, { id: 2, name: "Mushroom" } ]; this.test.next(toppingList); // 从加载的选项中匹配初始值(用id匹配,避免引用问题) const initialTopping = toppingList.find(t => t.id === 1); if (initialTopping) { this.toppingsControl.setValue([initialTopping]); } }, 5000); } onToppingRemoved(topping: { id: number; name: string }) { // 正确处理对象数组 const currentToppings = [...this.toppingsControl.value]; // 拷贝数组,避免直接修改原数组 const index = currentToppings.findIndex(t => t.id === topping.id); if (index !== -1) { currentToppings.splice(index, 1); this.toppingsControl.setValue(currentToppings); } } }
HTML代码
<mat-form-field> <mat-label>Toppings</mat-label> <mat-select [formControl]="toppingsControl" multiple> <mat-select-trigger> <mat-chip-list> <!-- 确保遍历的是FormControl的有效值,添加空值判断 --> <mat-chip *ngFor="let topping of toppingsControl.value || []" [removable]="true" (removed)="onToppingRemoved(topping)"> {{ topping.name }} <mat-icon matChipRemove>cancel</mat-icon> </mat-chip> </mat-chip-list> </mat-select-trigger> <mat-option *ngFor="let topping of toppingList$ | async" [value]="topping">{{topping.name}}</mat-option> </mat-select> </mat-form-field> <br/> {{ toppingsControl?.value | json }}
关键修改点说明
- 解决引用问题:在异步加载选项后,从返回的选项数组里找到匹配id的对象,再设置给FormControl,这样选中值和选项的引用一致,mat-select能正确识别。
- 明确类型:给FormControl指定明确的泛型类型,避免类型错误,同时让代码更清晰。
- 安全遍历:在
*ngFor里添加|| [],确保当FormControl值为空时不会报错,同时保证chip列表能正确渲染。 - 修复移除逻辑:用
findIndex通过id匹配对象,而不是indexOf(依赖引用),这样即使引用不同,只要id一致就能正确移除,同时拷贝数组再修改,避免直接操作FormControl的原数组值。
这样修改后,初始值的mat-chip就能在选项加载后正常渲染,移除功能也能正常工作啦!
内容的提问来源于stack exchange,提问作者Abhishek_054
相关产品推荐
相关产品推荐

