Reputation:
I am not very experienced in Angular 4 so I am not sure how this problem works. I get the following error;
ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'true'. Current value: 'false'.
Here is my setup. I have a component "menus.component.ts" (MenusComponent) which loads other components using <router-outlet></router-outlet>
The error happens at LocalService.placementListShow.value
in the code below.
<div class="row">
...
</div>
<!-- end row -->
<div class="row">
<div class="col-md-4 col-sm-4 col-xs-12 col-xl-3" *ngIf="LocalService.placementListShow.value">
<div class="card m-b-20" *ngIf="LocalService.AllPlacements.Loaded && !LocalService.AllPlacements.Loading">
...
<button type="button" class="list-group-item" [ngClass]="{'active': LocalService.AllPlacements.Active.value==placement.id }" (click)="LocalService.AllPlacements.Activate(placement.id)" *ngFor="let placement of LocalService.AllPlacements.Placements">{{placement.title}}</button>
...
</div>
<single-element-loader *ngIf="LocalService.AllPlacements.Loading"></single-element-loader>
</div><!-- end col-->
<div class="col-md-4 col-sm-4 col-xs-12 col-xl-3" *ngIf="LocalService.menuListShow.value">
...
<a [routerLink]="[menu.id]" class="list-group-item" [ngClass]="{'active': LocalService.PlacementMenus.Active.value==menu.id }" (click)="LocalService.PlacementMenus.Activate(menu.id)" *ngFor="let menu of LocalService.PlacementMenus.Menus">{{menu.title}}</a>
...
<single-element-loader *ngIf="LocalService.PlacementMenus.Loading"></single-element-loader>
</div><!-- end col-->
<div class="col-md-8 col-sm-8 col-xs-12 col-xl-9">
<router-outlet></router-outlet>
</div><!-- end col-->
</div>
The idea is that the component will load child components using Angular router. I want to control the visibility of certain widgets of the main component in the child components so I have setup a local service.
@Injectable()
export class LocalService {
menuListShow = new BehaviorSubject(false);
placementListShow = new BehaviorSubject(true);
Menu: Menu = new Menu();
AllPlacements: AllPlacements = new AllPlacements();
PlacementMenus: PlacementMenus = new PlacementMenus();
constructor(
private MenuService: MenuService,
private route: ActivatedRoute,
) {
}
changeMenuComponents(componentName: string): void {
alert ("Changing to: "+ componentName)
let menuState = {
'placementList': (that): void => {
that.menuListShow.next(false);
that.placementListShow.next(true);
},
'menuList': (that): void => {
that.placementListShow.next(false);
that.menuListShow.next(true);
}
};
menuState[componentName](this);
}
}
For example. I have a MenuComponent and EditLinkComponent which will be loaded in the MenusComponent. There are 2 widgets which I would like to show depending on what component is loaded in the main component. But using the service I get the error above.
The following is not so important but to give you more idea about what I am trying to do.
I would like to show a menu placement listing when the user is seeing the index of the MenusComponent and when I click on the menu placement it should show menus in that placement and when I click on the menu it should show links in the menu. When I click on edit link it should show the EditLinkComponent. This happens through Angular router for example; #cms/menus then #cms/menus/{menuid} then #cms/menus/{menuid}/links/{linkid}/edit
The problem is if I refresh at; #cms/menus/{menuid}/links/{linkid}/edit I have get the error;
ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'true'. Current value: 'false'.
And I think this has to do with attempting to load the placement object and menu object from the server.
Upvotes: 3
Views: 721
Reputation: 630
Here's how to fix it (you need to manually trigger a change detection):
@Injectable()
export class LocalService {
menuListShow = new BehaviorSubject(false);
placementListShow = new BehaviorSubject(true);
Menu: Menu = new Menu();
AllPlacements: AllPlacements = new AllPlacements();
PlacementMenus: PlacementMenus = new PlacementMenus();
constructor(
private changeDetectorRef: ChangeDetectorRef,
private MenuService: MenuService,
private route: ActivatedRoute,
) {
}
changeMenuComponents(componentName: string): void {
alert ("Changing to: "+ componentName)
let menuState = {
'placementList': (that): void => {
that.menuListShow.next(false);
that.placementListShow.next(true);
},
'menuList': (that): void => {
that.placementListShow.next(false);
that.menuListShow.next(true);
}
};
menuState[componentName](this);
this.changeDetectorRef.detectChanges();
}
}
Upvotes: 1