Angular 10中FormControl初始化mat-selection-list选项不勾选问题
问题核心根源
你遇到的列表选项不勾选的问题,是两个实现细节疏漏叠加导致的:
- Material 的
mat-selection-list判断选项选中状态的逻辑,是对 FormControl 的值和每个mat-list-option绑定的 value 做严格相等(===)匹配。你现在在选项上绑了整个cat对象作为value,而 FormControl 初始存的this.user.lstCategory是接口返回的独立对象实例,哪怕两个对象的字段、值完全一致,只要内存引用不同,匹配就会失败,自然不会触发选中状态。 - 两个异步服务请求的执行时序存在不可控风险:你把表单初始化逻辑绑在
getUser请求的完成回调里,但getAllCategory是独立发起的异步请求,完全可能出现表单已经初始化完成、分类列表数据还没返回的情况,此时mat-selection-list连选项都没渲染全,就算值的引用一致,也没法匹配到对应选项。
具体修复步骤
- 调整选项绑定的value,不要直接绑定整个分类对象,改用分类对象上的**唯一稳定标识(比如分类id)**作为选项值,从根源上避免对象引用匹配的问题。
- 调整FormControl的初始值格式,把用户信息里的分类对象数组,映射成和选项值一致的纯标识数组,确保两边的值可以通过严格相等校验。
- 梳理异步请求的执行时序,等两个接口都返回数据之后,再初始化表单和渲染组件,避免出现数据加载的空窗期。
调整后的参考代码
首先是TS逻辑调整:
// 引入forkJoin用于合并多个异步请求 import { forkJoin } from 'rxjs'; ngOnInit(): void { // 合并两个独立的异步请求,等全部响应完成再执行后续逻辑 forkJoin({ cbxCategory: this.categoryService.getAllCategory(), user: this.authService.getUser() }).subscribe({ next: (res) => { this.cbxCategory = res.cbxCategory; this.user = res.user; }, error: (err) => console.log(err), // 两个请求都完成后再初始化表单 complete: () => this.initForm() }) } private initForm() { this.editUserForm = this.formBuilder.group({ email: new FormControl(this.user.email, [Validators.required,Validators.pattern("^[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,6}$"),Validators.maxLength(50)]), password: new FormControl(''), passwordConfirm: new FormControl(''), // 把用户的分类数组映射为和选项value一致的id数组 lstCat: new FormControl(this.user.lstCategory.map(item => item.id)), }, { validator: MustMatch('password', 'passwordConfirm') }); }
然后是HTML模板调整:
<mat-selection-list formControlName="lstCat" class="col-md-12 col-sm-12"> <!-- 把原来绑定整个cat对象的value改成绑定cat的唯一id --> <mat-list-option *ngFor="let cat of cbxCategory" [value]="cat.id"> {{cat.libelle}} </mat-list-option> </mat-selection-list>
补充说明:如果业务逻辑需要获取选中选项的完整对象信息,不需要把value直接绑整个对象,可以在表单提交时,根据FormControl里存的id数组,从
cbxCategory列表中过滤匹配出对应的完整对象即可,既可以规避引用匹配的问题,也能降低组件的内存占用。
内容的提问来源于stack exchange,提问作者Jack Boch
相关产品推荐
相关产品推荐

