2017-07-30 82 views
1

我对Angular 4不是很有经验,所以我不确定这个问题是如何工作的。我得到以下错误;共享服务:ExpressionChangedAfterItHasBeenCheckedError:检查后表达式已更改

ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'true'. Current value: 'false'.

这是我的设置。我有一个使用<router-outlet></router-outlet>加载其他组件的组件“menus.component.ts”(MenusComponent)。错误发生在LocalService.placementListShow.value下面的代码中。

<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> 

想法是该组件将使用Angular路由器加载子组件。我想控制子组件中某些小部件的可见性,所以我设置了一个本地服务。

@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); 
    } 
} 

例如,我有一个MenuComponent和EditLinkComponent将被加载到MenusComponent中。根据主要组件中加载的组件,我想显示2个小部件。但使用服务,我得到上述错误。

以下内容并不重要,但让您更了解我正在尝试做什么。

我想显示一个菜单位置列表,当用户看到MenusComponent的索引时,当我点击菜单位置时,它应该在该位置显示菜单,当我点击菜单时,它应该显示链接菜单。当我点击编辑链接时,它应该显示EditLinkComponent。例如,这通过Angular路由器发生; #cms/menus然后#cms/menus/{menuid}然后#cms/menus/{menuid}/links/{linkid} /编辑

问题是如果我刷新; #cms/menus/{menuid}/links/{linkid} /编辑我得到错误;

ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'true'. Current value: 'false'.

我认为这与尝试从服务器加载放置对象和菜单对象有关。

+0

文章[所有你需要知道的关于'ExpressionChangedAfterItHasBeenCheckedError'错误](https://hackernoon.com/一切 - 你需要知道关于这个表达式changedafterithasbeencheckederror-error-e3fd9ce7dbb4)应该给你所有的答案 –

回答

0

以下是如何修复它(您需要手动触发变化检测):

@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(); 
    } 
}