Angular ngModelChange数据不一致问题:同名字段导致子组件获取错误对象
Angular ngModelChange数据不一致问题:同名字段导致子组件获取错误对象
最近碰到一个挺坑的Angular问题,跟大家说说具体情况和解决办法:
我有一个嵌套结构的数组数据,里面两个父对象的子分类subCategory里,name字段都是View,当我触发第二个子项的复选框ngModelChange事件时,在updateData方法里拿到的居然是第一个子项的数据,完全串了!
我的数据结构
[ { id: 'main_1', name: 'Sample', subCategory: [ { id: 'sub_2', name: 'View', permissions: [ {name: 'sample 1', description: 'description 1'} ], isPresent: true } ] }, { id: 'main_3', name: 'Sample 2', subCategory: [ { id: 'sub_4', name: 'View', permissions: [ {name: 'sample 2', description: 'description 2'} ], isPresent: true } ] } ]
组件代码结构
父组件从store取数,通过async管道循环传给子组件:
<div *ngFor="let item of (data|async);trackBy: trackByFn;"> <app-child [childData]="item"></app-child> </div>
子组件里循环subCategory渲染UI,复选框绑定了isPresent,并触发updateData:
<div *ngFor="let sub of childData.subCategory; let i = index; trackBy: trackByFnMain;"> <div> {{sub.name}} </div> <div> <input type="checkbox" [ngModel]="sub.isPresent" (ngModelChange)="updateData($event, sub)" > <label [for]="sub.name + i"></label> </div> </div>
排查与解决过程
一开始我以为是trackBy的问题,特意给子组件的循环加了基于subCategory.id的trackByFnMain:
trackByFnMain(index: number, subCategory: any): string { return subCategory.id; }
但问题还是没解决,直到我注意到label的for属性用了sub.name + i,而sub.name是重复的View,这会导致label和input的关联出问题;更关键的是,Angular在处理表单控件绑定的时候,如果有重复的标识,很容易出现数据串位的情况。
最终的解决办法是确保所有关联的标识都是唯一的:
- 把label的
for属性改成用sub.id(本身就是唯一值),或者组合sub.id + i这种绝对不会重复的字符串 - 确保
trackBy函数确实绑定到了唯一的字段(比如sub.id),让Angular能正确追踪每个子项的身份
简单来说,就是因为多个子项的name字段重复,导致表单控件的关联标识不唯一,进而让ngModel的事件绑定串了,换成唯一的id或者组合唯一值后,问题就彻底解决了!
备注:内容来源于stack exchange,提问作者Akhil paul
相关产品推荐
相关产品推荐

