简体   繁体   English

ExpressionChangedAfterItHasBeenCheckedError /角4角7

[英]ExpressionChangedAfterItHasBeenCheckedError / Angular 4-Angular 7

I updated my code from Angular 4 to Angular 7 and suddenly this error started emerging. 我将代码从Angular 4更新到了Angular 7,突然出现了这个错误。 There are soo many articles on the internet about this but non seems to work. 互联网上有太多关于此的文章,但似乎没有奏效。 Can someone please point me out why I am getting this error? 有人可以指出我为什么出现此错误吗? Error comes in the Breadcrums 错误来自面包屑

My Error 我的错误

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改。 Previous value: 'showBreadcrumbsSiteMetaData: false'. 先前的值:“ showBreadcrumbsSiteMetaData:false”。 Current value: 'showBreadcrumbsSiteMetaData: true'. 当前值:“ showBreadcrumbsSiteMetaData:true”。

at viewDebugError (core.js:20342)
at expressionChangedAfterItHasBeenCheckedError (core.js:20330)
at checkBindingNoChanges (core.js:20432)
at checkNoChangesNodeInline (core.js:23307)
at checkNoChangesNode (core.js:23292)
at debugCheckNoChangesNode (core.js:23896)
at debugCheckDirectivesFn (core.js:23824)
at Object.eval [as updateDirectives] (HomeComponent.html:6)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:23813)
at checkNoChangesView (core.js:23191)

Home.Component.html Home.Component.html

<div class="wrapper" >
  <navbar [metaData]="navBarMetadata" [userInfo]="navbarUserInfo" [helpButtonRoute]="navbarHelpButtonRoute"
        [menuItems]="sidebarRoutes" [settingsMenuItems]="settingsMenuItems"
        [languagesMenuItems]="languagesMenuItems"
        [rs_logo]="rs_logo"></navbar>
    <details-bar [breadscrumbsMetaData]="breadscrumbsMetaData" [breadcrumbsSiteMetaData]="breadcrumbsSiteMetaData"
             [showBreadcrumbsSiteMetaData]="showBreadcrumbsSiteMetaData"></details-bar>

  <div class="main-panel" #mainPanel (scroll)="onScroll($event)">
    <div class="container ">
      <div class="current-component">
        <simple-notifications [options]="notificationOptions"></simple-notifications>
        <router-outlet></router-outlet>
      </div>
    </div>
  </div>
</div>

Home.Component.ts Home.Component.ts

 export class HomeComponent implements OnInit, AfterViewInit {

    notificationOptions: any = AppConstants.NOTIFICATION_OPTIONS;
    sidebarRoutes: NavbarRouteInfo[];
    settingsMenuItems: NavbarRouteInfo[];
    navBarMetadata: NavBarMetadata[];
    navbarUserInfo: NavBarUserInfo;
    navbarHelpButtonRoute: string;
    rs_logo: string;
    languagesMenuItems: LanguageInfo[];
    breadscrumbsMetaData: BreadscrumbMetadata[];
    breadcrumbsSiteMetaData: BreadscrumbMetadata[];
    showBreadcrumbsSiteMetaData: boolean;
    entityTypeList: RSEntityType[];
    @ViewChild('mainPanel') mainPanelDiv: ElementRef;
    activeAppKey: string;
    protected alive = true;
    private notificationTitles: { error: string };

    constructor(public notificationsManager: NotificationsManager,
          private authGuard: AppAuthGuard,
          private homeEventBus: HomeEventBus,
          private userManagementService: UserManagementService,
          private homeService: HomeService,
          private authService: AuthService,
          private activatedRoute: ActivatedRoute,
          private translate: TranslateService,
          private dataService: DataService) {
          this.breadcrumbsSiteMetaData = [];
          this.showBreadcrumbsSiteMetaData = false;
          this.activeAppKey = '';
          this.entityTypeList = [];
          this.initMessages();}

          initMessages() {
             this.translate.stream('home.msg').subscribe((res) => {
             this.notificationTitles = {
             'error': res['error']
             }
          }
     );

}

ngOnInit() {

    this.notificationsManager.showSpinner();
    this.translate.setDefaultLang
    (sessionStorage.getItem(AppConstants.LANGUAGE));
    this.subscribeEvents();
    this.initNavBar();
    this.initSideBar();
    this.initLanguageBar();
    this.notificationsManager.hideSpinner();
}

ngAfterViewInit() {
    this.initNavBar();
    if (((this.activeAppKey) === undefined || (this.activeAppKey) === null) || 
    this.activeAppKey.trim().length === 0) {
    this.activeAppKey = sessionStorage.getItem(AppConstants.APP_KEY);
    }

    if (this.authGuard.isAccessTokenDefined()) {
    this.dataService.loadUserIdEmailList(this.activeAppKey);
    }
}

initNavBar() {
    this.rs_logo = environment.API_BASE_URL + '/' + 'resources/internal-assets/images?name=rs-logo.png';
    this.setNavBarMetaData();
    this.navbarHelpButtonRoute = AppConstants.HELP_ROUTE;
    this.navbarUserInfo = new NavBarUserInfo('assets/img/default-avatar.png', '');
    this.loadUserImg();
 }

 setNavBarMetaData() {
     this.translate.stream('navbar').subscribe((res) => {
         this.navBarMetadata = [{
             path: 'profile',
             params: {},
             title: res['profile'],
             index: -1
         }];
     });
 }


this.homeEventBus.breadcrumbsSiteMetaDataUpdateEvent$.subscribe(data => {
  if (data) {
    // this.fetchEntityTypes();
    this.showBreadcrumbsSiteMetaData = true;
  } else {
    // this.breadcrumbsSiteMetaData = [];
    this.showBreadcrumbsSiteMetaData = false;
  }
});

Usually this indicates a design flow, however, there are cases which the asynchronous pattern forces you to change things after angular checked it. 通常,这表示设计流程,但是,在某些情况下,异步模式会迫使您在进行角度检查后进行更改。

In order to re-initiate a change detection cycle, you have to 为了重新启动变更检测周期,您必须

Import ChangeDetectorRef 导入ChangeDetectorRef

import { ChangeDetectorRef } from '@angular/core';

Inject it in your component, 将其注入您的组件中,

public constructor(private readonly changeDetectorRef: ChangeDetectorRef) {
}

When you are certain to have completed the changes, mark your component as changed, and trigger the change 当您确定已完成更改时,将组件标记为已更改,然后触发更改

this.changeDetectorRef.markForCheck();
this.changeDetectorRef.detectChanges();

Please, be aware that you know control the detection cycle, therefore you must be sure you are not looping yourself asking to continuously to force the detection, otherwise you defeat the purpose of the all thing. 请注意,您知道控制检测周期,因此,您必须确保自己不会循环请求继续强制检测,否则会破坏万物的目的。

Update 更新

  this.homeEventBus.breadcrumbsSiteMetaDataUpdateEvent$
      .pipe(
          delay(0),
          tap(data => {
              if (data)
                this.showBreadcrumbsSiteMetaData = true;
              else
                this.showBreadcrumbsSiteMetaData = false;
            })
      ).subscribe();

or 要么

setTimeout(() => {
    this.homeEventBus.breadcrumbsSiteMetaDataUpdateEvent$.subscribe(data => {
      if (data) {
        // this.fetchEntityTypes();
        this.showBreadcrumbsSiteMetaData = true;
      } else {
        // this.breadcrumbsSiteMetaData = [];
        this.showBreadcrumbsSiteMetaData = false;
      }
    });
  });

your code might having issue as it modifying value of property in ngAfterViewInit , that might be cause of issue 您的代码在修改ngAfterViewInit的property的值时可能会出现问题,这可能是导致问题的原因

so you should put you code of ngAfterViewInit as bel 所以你应该把ngAfterViewInit的代码作为bel

ngAfterViewInit() {
   setTimeout(() => {
    this.initNavBar();
    if (((this.activeAppKey) === undefined || (this.activeAppKey) === null) || 
    this.activeAppKey.trim().length === 0) {
    this.activeAppKey = sessionStorage.getItem(AppConstants.APP_KEY);
    }

    if (this.authGuard.isAccessTokenDefined()) {
    this.dataService.loadUserIdEmailList(this.activeAppKey);
    }
  }
}

for detail check : https://blog.angular-university.io/angular-debugging/ 有关详细信息,请检查: https : //blog.angular-university.io/angular-debugging/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM