ExpressionChangedAfterItHasBeenCheckedError:Unable to detect
ExpressionChangedAfterItHasBeenCheckedError:Unable to detect
我有一个 angular 4 应用程序。
app.component.html看起来像这样
<!--The content below is only a placeholder and can be replaced.-->
<loading-bar color="#FF0000" [height]="3" [animationTime]="0.3" [runInterval]="100" [progress]="0"></loading-bar>
<div class="app app-header-fixed" value="test">
<app-header *ngIf="header" name="app_header"></app-header>
<app-left-menu *ngIf="leftmenu" name="app_leftMenu"></app-left-menu>
<div id="content" class="app-content abc_plain_wraper" role="main">
<router-outlet></router-outlet>
</div>
<app-right-menu *ngIf="rightmenu" name="app_rightMenu"></app-right-menu>
</div>
基本上在登录时它们是隐藏的,在成功登录后它们在注销时再次可见它们是隐藏的。
为此,我有一个 mange_component 服务,它在 header、右菜单和左菜单的值发生变化时发出事件。
管理组件服务方法
import { Component, NgModule, VERSION, Injectable, Output, EventEmitter} from '@angular/core';
import { ComponentStatus } from '../model/component-status';
import { Observable } from 'rxjs/Rx';
@Injectable()
export class ManageComponentStatusService {
@Output() OnChange: EventEmitter<any> = new EventEmitter();
@Output() ManageHeader: EventEmitter<any> = new EventEmitter();
componentStatus: any;
constructor() {
this.componentStatus = new ComponentStatus();
this.componentStatus.header = false;
this.componentStatus.leftMenu = false;
this.componentStatus.rightMenu = false;
this.componentStatus.plainHeader = true;
}
public setComponentStatus(header: any, left: any, right: any) {
this.componentStatus.header = header;
this.componentStatus.leftMenu = left;
this.componentStatus.rightMenu = right;
this.OnChange.emit(this.componentStatus);
}
public getComponentStatus(): Observable<any> {
return this.OnChange;
}
public setPlainHeader(status:any) {
this.componentStatus.plainHeader = status;
var self = this;
setTimeout(function () {
self.ManageHeader.emit(self.componentStatus.plainHeader);
}, 300);
}
public restoreHeader() {
this.componentStatus.plainHeader = true;
}
public getHeaderStatus(): Observable<any>{
return this.ManageHeader;
}
}
在 app.component.ts 中,我们设置了组件值,还有一个订阅来检查更改
export class AppComponent implements OnInit {
title = 'test App';
authSettings: any;
appConstants: any;
_router: any;
header: any=false;
leftmenu: any=false;
rightmenu: any=false;
compModel: any;
constructor(private ngAuthService: NgAuthService, private tenantServ: TenantService,
private loadingBarService: LoadingBarService, private router: Router,
public manageComp: ManageComponentStatusService,public socialServ: SocialMediaSettingsService) {
this._router = router;
this.authSettings = ngAuthService.getNgAuth();
this.appConstants = ngAuthService.getAppConstant();
//this.manageComp.setComponentStatus(false, false, false);
router.events.subscribe(event => {
if (event instanceof NavigationStart) {
this.loadingBarService.start();
//console.log("navigation start");
}
else if (event instanceof NavigationEnd) {
//console.log("navigation end");
this.loadingBarService.complete();
}
});
this.compModel = this.manageComp.getComponentStatus();
}
logOut() {
this.manageComp.setComponentStatus(false, false, false);
this._router.navigate(['login']);
}
ngOnInit() {
//this.header = this.compModel.header;
//this.leftmenu = this.compModel.leftMenu;
//this.rightmenu = this.compModel.rightMenu;
this._router.navigate(['login']);
/*subscribing to change*/
this.manageComp.getComponentStatus().subscribe(
data => {
this.header = data.header;
this.leftmenu = data.leftMenu;
this.rightmenu = data.rightMenu;
});
}
ngOnChanges() {
alert("change detected");
}
}
登录成功后加载的路由是abc
下面是 abc 组件。我只添加相关部分
ngOnInit() {
this.compStatus.setComponentStatus(true, true, true);//UPDATING HERE
this.userServ.setUserProfile();
this.compStatus.setPlainHeader(true);
this.opts = {
barBackground: '#C9C9C9',
gridBackground: '#D9D9D9',
barBorderRadius: '1',
barWidth: '2',
gridWidth: '1'
};
this.socialMediaData = this.socialSetServ.getSocialProvider();
this.isContentEditable = this.commonServ.getAppConfig().contentEditable;
}
当登录页面加载时,出现此异常。
ng:///AppModule/AppComponent.ngfactory.js:40 ERROR Error:
ExpressionChangedAfterItHasBeenCheckedError: Expression has changed
after it was checked. Previous value: 'undefined'. Current value:
'false'.
我知道我与删除更改有关,但不知道如何更正。
This error happens because the value of the variable changed before
change Detection can work on the previous one.
A work around for this is to use The setTimeout function schedules a
macrotask then will be executed in the following VM turn.
你可以把这段代码 this.compStatus.setComponentStatus(true, true, true);
放在 set Timeout
里面
setTimeout(() => {
this.compStatus.setComponentStatus(true, true, true);
}, 0);
我有一个 angular 4 应用程序。
app.component.html看起来像这样
<!--The content below is only a placeholder and can be replaced.-->
<loading-bar color="#FF0000" [height]="3" [animationTime]="0.3" [runInterval]="100" [progress]="0"></loading-bar>
<div class="app app-header-fixed" value="test">
<app-header *ngIf="header" name="app_header"></app-header>
<app-left-menu *ngIf="leftmenu" name="app_leftMenu"></app-left-menu>
<div id="content" class="app-content abc_plain_wraper" role="main">
<router-outlet></router-outlet>
</div>
<app-right-menu *ngIf="rightmenu" name="app_rightMenu"></app-right-menu>
</div>
基本上在登录时它们是隐藏的,在成功登录后它们在注销时再次可见它们是隐藏的。
为此,我有一个 mange_component 服务,它在 header、右菜单和左菜单的值发生变化时发出事件。
管理组件服务方法
import { Component, NgModule, VERSION, Injectable, Output, EventEmitter} from '@angular/core';
import { ComponentStatus } from '../model/component-status';
import { Observable } from 'rxjs/Rx';
@Injectable()
export class ManageComponentStatusService {
@Output() OnChange: EventEmitter<any> = new EventEmitter();
@Output() ManageHeader: EventEmitter<any> = new EventEmitter();
componentStatus: any;
constructor() {
this.componentStatus = new ComponentStatus();
this.componentStatus.header = false;
this.componentStatus.leftMenu = false;
this.componentStatus.rightMenu = false;
this.componentStatus.plainHeader = true;
}
public setComponentStatus(header: any, left: any, right: any) {
this.componentStatus.header = header;
this.componentStatus.leftMenu = left;
this.componentStatus.rightMenu = right;
this.OnChange.emit(this.componentStatus);
}
public getComponentStatus(): Observable<any> {
return this.OnChange;
}
public setPlainHeader(status:any) {
this.componentStatus.plainHeader = status;
var self = this;
setTimeout(function () {
self.ManageHeader.emit(self.componentStatus.plainHeader);
}, 300);
}
public restoreHeader() {
this.componentStatus.plainHeader = true;
}
public getHeaderStatus(): Observable<any>{
return this.ManageHeader;
}
}
在 app.component.ts 中,我们设置了组件值,还有一个订阅来检查更改
export class AppComponent implements OnInit {
title = 'test App';
authSettings: any;
appConstants: any;
_router: any;
header: any=false;
leftmenu: any=false;
rightmenu: any=false;
compModel: any;
constructor(private ngAuthService: NgAuthService, private tenantServ: TenantService,
private loadingBarService: LoadingBarService, private router: Router,
public manageComp: ManageComponentStatusService,public socialServ: SocialMediaSettingsService) {
this._router = router;
this.authSettings = ngAuthService.getNgAuth();
this.appConstants = ngAuthService.getAppConstant();
//this.manageComp.setComponentStatus(false, false, false);
router.events.subscribe(event => {
if (event instanceof NavigationStart) {
this.loadingBarService.start();
//console.log("navigation start");
}
else if (event instanceof NavigationEnd) {
//console.log("navigation end");
this.loadingBarService.complete();
}
});
this.compModel = this.manageComp.getComponentStatus();
}
logOut() {
this.manageComp.setComponentStatus(false, false, false);
this._router.navigate(['login']);
}
ngOnInit() {
//this.header = this.compModel.header;
//this.leftmenu = this.compModel.leftMenu;
//this.rightmenu = this.compModel.rightMenu;
this._router.navigate(['login']);
/*subscribing to change*/
this.manageComp.getComponentStatus().subscribe(
data => {
this.header = data.header;
this.leftmenu = data.leftMenu;
this.rightmenu = data.rightMenu;
});
}
ngOnChanges() {
alert("change detected");
}
}
登录成功后加载的路由是abc 下面是 abc 组件。我只添加相关部分
ngOnInit() {
this.compStatus.setComponentStatus(true, true, true);//UPDATING HERE
this.userServ.setUserProfile();
this.compStatus.setPlainHeader(true);
this.opts = {
barBackground: '#C9C9C9',
gridBackground: '#D9D9D9',
barBorderRadius: '1',
barWidth: '2',
gridWidth: '1'
};
this.socialMediaData = this.socialSetServ.getSocialProvider();
this.isContentEditable = this.commonServ.getAppConfig().contentEditable;
}
当登录页面加载时,出现此异常。
ng:///AppModule/AppComponent.ngfactory.js:40 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: 'false'.
我知道我与删除更改有关,但不知道如何更正。
This error happens because the value of the variable changed before change Detection can work on the previous one.
A work around for this is to use The setTimeout function schedules a macrotask then will be executed in the following VM turn.
你可以把这段代码 this.compStatus.setComponentStatus(true, true, true);
放在 set Timeout
setTimeout(() => {
this.compStatus.setComponentStatus(true, true, true);
}, 0);