简体   繁体   English

ExpressionChangedAfterItHasBeenCheckedError:检查后表达式已更改。 以前的值:'ngIf:true'。 当前值:'ngIf:false'

[英]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的值在初始化过程中更改了两次:

  • once during the service SerService creation and一次在服务SerService创建和
  • again in 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.

相关问题 ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改。 先前的值:&#39;ngIf:false&#39;。 当前值:&#39;ngIf:true&#39; - ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: false'. Current value: 'ngIf: true' 检查后表达式已更改。 'ng-untouched' 的先前值:'true'。 当前值:“假” - Expression has changed after it was checked. Previous value for 'ng-untouched': 'true'. Current value: 'false' ExpressionChangedAfterItHasBeenCheckedError:从ckEditor获取值时检查后表达式已更改 - ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked while getting the value from ckEditor 检查后表达式已更改。 Angular 2问题 - Expression has changed after it was checked. Angular 2 issue ExpressionChangedAfterItHasBeenCheckedError:使用Angular2检查表达式后,表达式已更改 - ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked using Angular2 更改动态颜色 - ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改 - change dynamic color - ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked ngu-carousel :: :: ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改 - ngu-carousel :: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked 共享服务:ExpressionChangedAfterItHasBeenCheckedError:检查表达式后,表达式已更改 - Shared service: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked ngIf 中的 ExpressionChangedAfterItHasBeenCheckedError? - ExpressionChangedAfterItHasBeenCheckedError in ngIf? 基于下拉值的 Angular 8 ngIf 表达式 - Angular 8 ngIf expression based on the drop down value
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM