@ViewChild(CdkPortalOutlet)在AfterViewInit中返回未定义

时间:2019-01-05 18:30:13

标签: javascript angular angular-cdk

尝试用ng-template查询CdkPortalOutlet总是不成功,我不明白为什么?

<ng-template CdkPortalOutlet></ng-template>

@ViewChild(CdkPortalOutlet) test: CdkPortalOutlet;

stackblitz

2 个答案:

答案 0 :(得分:3)

要在CdkPortalOutlet模板中使用AppComponent伪指令,您需要在PortalModule中导入AppModule(即,已声明AppComponent的NgModule)

import { PortalModule } from '@angular/cdk/portal';
...

@NgModule({
  imports:      [ BrowserModule, FormsModule, PortalModule, OverlayModule ],
                                              ^^^^^^^^^^^^
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }

Angular HTML解析器也是区分大小写的,因此您需要像这样使用它:

<ng-template cdkPortalOutlet></ng-template>
             ^^^
          lower case

Forked Stackblitz

答案 1 :(得分:1)

由于Angular 8 @ViewChild需要提供一个额外的static参数,因此文档很难找到将其设置为什么值。如果未正确设置,则尝试使用undefined来检索CdkPortalOutlet时,将得到一个@ViewChild值。

TLDR

在迁移到Angular 8时设置@ViewChild(CdkPortalOutlet, { static: true })

从Angular代码中提取注释

如何选择要使用的static标志值:truefalse

我们始终建议在ngAfterContentInit中检索内容查询的查询结果。 这是因为到该生命周期挂钩运行时,相关节点的更改检测已经完成,并且我们可以保证我们已经收集了所有可能的查询结果。

出于这个原因,大多数应用程序都希望使用{static: false}。此设置将确保查询找到依赖于绑定分辨率的查询匹配项(例如*ngIf*ngFor内的结果)。 如果您需要访问查询中的TemplateRef才能动态创建视图,则无法在ngAfterContentInit中进行操作。 更改检测已在该视图上运行,因此使用模板创建新视图将引发ExpressionHasChangedAfterChecked错误。 在这种情况下,您需要将static标志设置为true并在ngOnInit中创建视图。 在大多数其他情况下,最佳做法是使用{static: false}

但是,为了方便向版本8的迁移,如果您的组件代码已经取决于查询结果在之前的某个时间可用,则可能还需要将static标志设置为true ngAfterContentInit。 例如,如果您的组件依赖于在ngOnInit挂钩或@Input设置器中填充的查询结果,则需要将标志设置为true或重新处理组件以适应以后的时间。

注意:选择静态选项意味着嵌套在*ngIf*ngFor中的查询结果将不会被查询找到。 这些结果只有在进行更改检测后才能获取。