首页 文章

动态创建的组件中的Angular ExpressionChangedAfterItHasBeenCheckedError

提问于
浏览
0

我正在面对Angular的问题和来自 @angular/cdkCdkPortal / CdkPortalHost .
我创建了一个服务,允许我注册一个具有给定名称的 CdkPortalHost ,并在任何时候设置它 Component .

该服务看起来像这样:

private portalHosts : { [location : string] : CdkPortalOutlet } = {};
private portals : { [location : string] : any} = {};

/** Sets the PortalHost for the given location. */
public register(location : string, portalHost : CdkPortalOutlet) {
    this.portalHosts[location] = portalHost;
}

/** Sets the Component for the given location. */
public setComponent<T>(location : string, type : ComponentType<T>) : ComponentRef<T> {
    let ref : ComponentRef<T> = null;
    let portalHost = this.portalHosts[location];
    if (portalHost) {
        if (portalHost.hasAttached()) {
            portalHost.portal.detach();
            this.portals[location] = null;
        }
        ref = portalHost.attachComponentPortal(new ComponentPortal(type));
        this.portals[location] = ref.instance;
    }
    return ref;
}

然后我注册了一个像这样的PortalHost:

@ViewChild(PortalHostDirective)
private portalHost : PortalHostDirective;

public ngAfterContentInit() {
    this.dynamicComponentService.register("Location", this.portalHost);
}

在另一个组件中,它是注册PortalHost的Component的子组件,我将动态组件设置为:

public ngAfterContentInit() {
    this.dynamicComponentService.setComponent("Location", MyDynamicComponent);
}

出于测试目的,我使用MyDynamicComponent的简单模板:

<div *ngIf="true">Test</div>

现在,当我运行App时,我收到以下错误:

Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.
Previous value: 'undefined'. Current value: 'true'.
It seems like the view has been created after its parent and its children have been dirty checked.
Has it been created in a change detection hook ?

我见过几个类似的问题,但"window.setTimeout" -Workaround对我不起作用 .
我也为PortalHost-Registration和Component-Creation尝试了不同的生命周期钩子,但结果总是一样的......

我使用的是Angular 5.0.1和Material / CDK 5.0.0-rc0 .

我错过了什么或这是一个错误吗?
它与Angular/Material#5268有关吗?

1 回答

  • 0

    ngAfterContentInit 对于门户网站插座的更改检测生效可能为时过早 . 在注册门户网站插座并在 ngOnInit 中注册组件时,我遇到了这个确切的问题:

    this.tabPortalHost = new DomPortalOutlet(
      this.tabContentOutlet.nativeElement,
      this.componentFactoryResolver,
      this.appRef,
      this.injector
    );
    
    
    const portal = new ComponentPortal(this.tabs[0], null, this.injector);
    this.tabPortalHost.attach(portal);
    

    setTimeout 中包装最后一行时,代码按预期工作 .

相关问题