Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular ExpressionChangedTerithasBeenCheckedError:通过迭代映射_Angular_Rxjs - Fatal编程技术网

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无法以正确的方式检测到更改。