Angular ExpressionChangedTerithasBeenCheckedError:通过迭代映射
我有一个简单的角度组件,在渲染时抛出以下错误:Angular ExpressionChangedTerithasBeenCheckedError:通过迭代映射,angular,rxjs,Angular,Rxjs,我有一个简单的角度组件,在渲染时抛出以下错误: MyComponent.html:10 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngForOf: [object Map Iterator]'. Current value: 'ngForOf: [object Map Iterator]'. 该错
MyComponent.html:10 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.
Previous value: 'ngForOf: [object Map Iterator]'.
Current value: 'ngForOf: [object Map Iterator]'.
该错误会抛出两次,即使在没有其他代码的情况下移动到最小角度的裸项目(只有包装该组件的AppComponent)也是如此
我将代码最小化到最简单的形式,仍然可以重现问题。我用一个硬编码的可观察对象替换了数据服务
组成部分
@组件({
选择器:“我的组件”,
templateUrl:“./my.component.html”,
样式URL:['./my.component.scss'],
})
导出类MyComponent实现OnInit、OnDestroy{
私人cobs:地图;
私人分包:认购;
构造函数(){}
恩戈尼尼特(){
//最初数据来自服务。。。
this.cobSub=of(新映射([[1,'a'],[2,'b']]))
.订阅({
下一步:cobs=>{this.cobs=cobs;},
});
}
ngOnDestroy():void{
this.cobSub.unsubscribe();
}
}
请注意,asyncPipe
在这种场景中更常用,但我不能使用它
模板
身份证件
业务类别
{{key}}
{{cobs.get(key)}
为什么会出现问题
如何修复它?这是您在地图上迭代的方式的问题,您可以尝试:
export class AppComponent implements OnInit {
private cobs = new Map<number, string>();
private cobSub: Subscription;
constructor() {}
ngOnInit() {
this.cobSub = of(new Map<number, string>([[1, 'a'], [2, 'b']]))
.subscribe( cobs => {
this.cobs = cobs;
});
}
getKeys(map){
return Array.from(map.keys()); // add it
}
ngOnDestroy(): void {
this.cobSub.unsubscribe();
}
}
导出类AppComponent实现OnInit{
私有cobs=新映射();
私人分包:认购;
构造函数(){}
恩戈尼尼特(){
this.cobSub=of(新映射([[1,'a'],[2,'b']]))
.订阅(cobs=>{
this.cobs=cobs;
});
}
getKeys(地图){
返回Array.from(map.keys());//添加它
}
ngOnDestroy():void{
this.cobSub.unsubscribe();
}
}
在html中:
<div>
<table *ngIf="cobs">
<tr>
<th>Id</th>
<th>Class of Business</th>
</tr>
<tr *ngFor="let key of getKeys(cobs)">
<td>{{key}}</td>
<td>{{cobs.get(key)}}</td>
</tr>
</table>
</div>
身份证件
业务类别
{{key}}
{{cobs.get(key)}
如果您使用的是Angular 6.1+,则可以使用默认管道keyvalue:
<tr *ngFor="let key of cobs | keyvalue">
<td>{{key.key}}</td>
<td>{{key.value}}</td>
</tr>
{{key.key}}
{{key.value}}
尝试在ngAfterViewInit中填充this.cobSub。@FatemeFazli ngAfterViewInit():void{this.cobSub=new Subscription();}并实现AfterViewInit
接口-没有帮助。为什么要这样做?ngAfterViewInit(){//最初数据来自一个服务…this.cobSub=of(新映射([[1,'a'],[2,'b']])。订阅({next:cobs=>{this.cobs=cobs;},},});}
@FatemeFazli我将onInit
代码移动到ngAfterViewInit
。它没有帮助+我不明白为什么OnInit对于这个代码来说不够好。谢谢!这很奇怪,但我真的想知道为什么?map.keys()是有效的iterable。映射键是数字,所以我不能使用keyValuePipe。这是因为绑定到模板中的方法…keys()。每次运行更改检测时都会调用它。object.keys()每次调用时都会返回一个新对象,Angular会将其识别为意外更改,这会导致错误。getKeys(cobs)
每次都通过调用array.from生成一个新数组。区别是什么?map.keys()返回一个iterable,但getKeys(cobs)返回它的数组。如果您更改为getKeys(map){console.log(map,map.keys(),Array.from(map.keys()))返回Array.from(map.keys();}
您可以看到map.keys()是一个复杂的映射迭代器对象,我认为angular无法以正确的方式检测到更改。