[英]ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: true'. Current value: 'ngIf: false'
I have an Angular 10 application, I am trying to remove the navside component from the login component, so I created a service on the nave side component contains this code :我有一个 Angular 10 应用程序,我试图从登录组件中删除导航端组件,所以我在导航端组件上创建了一个包含以下代码的服务:
visible: boolean;
constructor() {
this.visible = true;
}
show() {
this.visible = true;
}
hide() {
this.visible = false;
}
toggle() {
this.visible = !this.visible;
}
doSomethingElseUseful() { }
and inside the naveside component i put :在 naveside 组件中,我放了:
export class NavsideComponent implements OnInit {
constructor(public sr: ServService ) { }
ngOnInit(): void {
}
and the Html component :和 Html 组件:
<div *ngIf="sr.visible">
<mat-sidenav-container class="example-container">
<mat-sidenav #sidenav mode="push" class="app-sidenav" opened>
<mat-toolbar class="co">
<span class="toolbar-filler"></span>
.
.
.
.
.
. </div>
but this error was displayed :但显示此错误:
ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: true'. Current value: 'ngIf: false'.
EDIT 1编辑 1
Login.component.ts登录.component.ts
import { Component, OnInit } from '@angular/core';
import { ServService } from '../../navside/serv.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
constructor( private sr :ServService) { }
ngOnInit(): void {
this.sr.hide();
this.sr.doSomethingElseUseful();
}
}
EDIT 2编辑 2
Stackblitz putting together the snippets above, where the warning can be seen: Stackblitz 将上面的片段放在一起,可以看到警告:
https://stackblitz.com/edit/angular-ivy-vbkytu?file=src/app/login/login.component.ts https://stackblitz.com/edit/angular-ivy-vbkytu?file=src/app/login/login.component.ts
I have edited your post to include a Stackblitz with a minimal reproducible example of the reported error.我已经编辑了您的帖子,以包含一个 Stackblitz,其中包含报告错误的最小可重现示例。 I suggest that in your next posts you include a minimal reproducible example , hence it´s more likelly you will have an answer.我建议在您的下一篇文章中包含一个最小的可重复示例,因此您更有可能得到答案。
About ExpressionChangedAfterItHasBeenCheckedError warning关于 ExpressionChangedAfterItHasBeenCheckedError 警告
This post has usefull informations about this warning: Expression ___ has changed after it was checked这篇文章有关于这个警告的有用信息: Expression ___ has changed after it is checked
In your specific case, the warning ExpressionChangedAfterItHasBeenCheckedError
is shown because the value of sr.visible
is changed twice during the initialization process:在您的特定情况下,显示警告ExpressionChangedAfterItHasBeenCheckedError
是因为sr.visible
的值在初始化过程中更改了两次:
SerService
creation and一次在服务SerService
创建和loginComponent.ngOnInit()
when you call sr.hide()
;当您调用sr.hide()
时再次在loginComponent.ngOnInit()
sr.hide()
; In the same round of change detection a value that is binded in the view ( sr.visible
is binded in <div *ngIf="sr.visible">
) is not supposed to change values more than once, that's the reason of the warning.在同一轮更改检测中,视图中绑定的值( sr.visible
绑定在<div *ngIf="sr.visible">
)不应多次更改值,这就是警告的原因.
Solving your problem calling cdr.changeDetection() in the right component解决在正确的组件中调用 cdr.changeDetection() 的问题
You can solve the problem calling cdr.detectChanges()
in order to fire a second round of change detections.您可以通过调用cdr.detectChanges()
来解决该问题,以启动第二轮更改检测。 But for that to work, you need to call it in the component that has the affected binding .但是要使其工作,您需要在具有受影响 binding的组件中调用它。
Calling cdr.detectChanges() on LoginComponent has no effect , since the binding of <div *ngIf="sr.visible">
is not in that component.上LoginComponent调用cdr.detectChanges()没有效果,因为结合<div *ngIf="sr.visible">
不在该组件。 You should call cdr.detectChanges() in the parent component where the binding is.您应该在绑定所在的父组件中调用 cdr.detectChanges() 。
That said, the following use of cdr.detectChanges() in LoginComponent will NOT solve the problem :也就是说,以下在 LoginComponent 中使用 cdr.detectChanges()不会解决问题:
export class LoginComponent {
constructor(private sr: ServService, private cdr: ChangeDetectorRef) {}
ngOnInit() {
this.sr.hide();
this.sr.doSomethingElseUseful();
//code bellow will NOT SOLVE the problem:
this.cdr.detectChanges();
}
}
What will solve the problem is invoking cdr.detectChanges() on the component that has the binding <div *ngIf="sr.visible">
.可以解决问题的是在具有绑定<div *ngIf="sr.visible">
的组件上调用 cdr.detectChanges() 。
In my working stackblitz (at the end of this answer), that component is AppComponent:在我的工作堆栈闪电战中(在本答案的末尾),该组件是 AppComponent:
app.component.html
: app.component.html
:
<div *ngIf="sr.visible">
Toolbar here
<!-- your mat-side-nav and mat-toolbar here -->
</div>
<app-login></app-login>
So, the cdr.detectChanges()
is called in the ngOnInit()
of app.component.ts
:因此, cdr.detectChanges()
被调用的ngOnInit()
的app.component.ts
:
export class AppComponent {
constructor(public sr: ServService,
private cdr: ChangeDetectorRef) {}
ngOnInit() {
this.cdr.detectChanges();
}
}
Working version - stackblitz工作版本 - stackblitz
The working version calling detectChanges in the right component is available in the following Stackblitz:以下 Stackblitz 中提供了在正确组件中调用 detectChanges 的工作版本:
https://stackblitz.com/edit/angular-ivy-nbb7bz?file=src/app/app.component.ts https://stackblitz.com/edit/angular-ivy-nbb7bz?file=src/app/app.component.ts
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.