我的子模块中的每个EventEmiiter都会出现此错误,但我无法找到解决方法。
ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'true'. Current value: 'false'.
这是触发我的EventEmitter的原因:
ngOnChanges(changes: any) {
if (changes.groupingTabValid) {
if (changes.groupingTabValid.currentValue !== changes.groupingTabValid.previousValue) {
this.groupingTabValidChange.emit(this.groupingTabValid);
}
}
}
这是我的“主要”组件的HTML
<year-overview-grouping [definitionDetails]="definitionDetails"
[fixedData]="fixedData"
[showValidation]="showValidation"
[groupingTabValid]="groupingTabValid"
(groupingTabValidChange)="setValidators('groupingTab', $event)">
</year-overview-grouping>
调用此功能
public setValidators(validator: string, e: boolean) {
switch (validator) {
case "groupingTab":
this.groupingTabValid = e;
break;
case "selectionTab":
this.selectionTabValid = e;
break;
}
if (this.groupingTabValid && this.selectionTabValid) {
this.valid = true;
} else {
this.valid = false;
}
}
1)在一个简单的解释中,是什么导致了这个错误?
2)我可以采取哪些措施来解决这个问题?
答案 0 :(得分:11)
遵守单向数据流规则
尝试使用setTimeout
推迟对一个tick的调用if (changes.groupingTabValid.currentValue !== changes.groupingTabValid.previousValue) {
setTimeout(() => this.groupingTabValidChange.emit(this.groupingTabValid), 0)
}
答案 1 :(得分:4)
只需导入ChangeDetectionStrategy,然后将其添加到您的组件
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'app-bla-bla-bla',
templateUrl: './xxxxx'
})
答案 2 :(得分:2)
您可以避免使用setTimeout
并告诉Angular在初步检查后即将发生更改。
您可以将ChangeDetectorRef
注入您的组件并使用其markForCheck
方法。
/* ... */
constructor(private cdr: ChangeDetectorRef) {}
/* ... */
if (changes.groupingTabValid.currentValue !== changes.groupingTabValid.previousValue {
this.cdr.markForCheck();
this.groupingTabValidChange.emit(this.groupingTabValid);
}
答案 3 :(得分:1)
我自己刚开始看这个异常类型,所以没有专家,但是假设它是在那里停止反馈循环。
我看不出任何明显的原因,你想要将值发送给孩子并备份到父,但假设孩子应用了一些额外的逻辑。 对我来说,在服务而不是子组件中应用任何其他逻辑似乎更好。
我意识到plunker代码没有循环,但Angular机制似乎相当简单 - 只需在循环结束时重新检查值。请注意,您的问题代码中的 groupingTabValid 会直接反馈。
查看给定的plunker代码,从结构上来说,可以在父级上处理对年龄的更改。 click事件将为(click)=changeAge(age.value)
,并且方法(在父级上)可以处理它
changeAge(inputAge) {
this.newAge = inputAge;
this.person.age = inputAge;
}
这是一个掠夺者的叉子。 Modified plunker
子组件仍然更新person.age,但不再导致错误,因为该值与父项上设置的值相同。
答案 4 :(得分:-3)
我有同样的问题。为了解决这个问题,我做了这个小小的黑客攻击。
setTimeout((()=>this.valueSelect.emit(idChange)), 0);
其中“this.valueSelect.emit(idChange)”是我将发出的变化