共享服务:ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后发生了变化

时间:2017-07-30 13:16:02

标签: javascript jquery angular typescript

我对Angular 4不是很有经验,所以我不确定这个问题是如何工作的。我收到以下错误;

  

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

这是我的设置。我有一个组件&#34; menus.component.ts&#34; (MenusComponent)使用<router-outlet></router-outlet>加载其他组件错误发生在下面代码中的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} / edit

问题是如果我刷新; #cms / menus / {menuid} / links / {linkid} / edit我收到了错误;

  

错误错误:ExpressionChangedAfterItHasBeenCheckedError:检查后表达式已更改。以前的价值:&#39; true&#39;。当前价值:&#39; false&#39;。

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

1 个答案:

答案 0 :(得分: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();
  }
}