@ViewChild(CdkPortalOutlet) returns 在 AfterViewInit 中未定义
@ViewChild(CdkPortalOutlet) returns undefined in AfterViewInit
尝试用 CdkPortalOutlet
查询 ng-template
总是不成功,我不明白为什么?
<ng-template CdkPortalOutlet></ng-template>
@ViewChild(CdkPortalOutlet) test: CdkPortalOutlet;
为了在 AppComponent
模板中使用 CdkPortalOutlet
指令,您必须在 AppModule
中导入 PortalModule
(即已声明 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
因为 Angular 8 @ViewChild
需要提供一个额外的 static
参数,并且很难找到关于将其设置为什么值的文档。如果设置不正确,当尝试使用 @ViewChild
.
检索 CdkPortalOutlet
时,将导致 undefined
值
TLDR
迁移到 Angular 8.
时设置 @ViewChild(CdkPortalOutlet, { static: true })
从 Angular 代码中提取注释
如何选择要使用的 static
标志值:true
或 false
?
对于内容查询,我们一直建议在 ngAfterContentInit
中检索查询结果。
这是因为到这个生命周期钩子 运行s 时,相关节点的变化检测已经完成,我们可以保证我们已经收集了所有可能的查询结果。
出于这个原因,大多数应用程序都希望使用 {static: false}
。此设置将确保查询找到依赖于绑定解析的查询匹配项(例如 *ngIf
s 或 *ngFor
s 内的结果)。
如果您需要访问查询中的 TemplateRef
以动态创建视图,则无法在 ngAfterContentInit
中执行此操作。
更改检测已经对该视图进行了 运行,因此使用模板创建新视图将导致抛出 ExpressionHasChangedAfterChecked
错误。
在这种情况下,您需要将 static
标志设置为 true
并在 ngOnInit
中创建您的视图。
在大多数其他情况下,最佳做法是使用 {static: false}
.
但是,为了便于迁移到版本 8,如果您的组件代码已经依赖于某个时间可用的查询结果,您可能还需要将 static
标志设置为 true
之前ngAfterContentInit
。
例如,如果您的组件依赖于在 ngOnInit
挂钩或 @Input
设置器中填充的查询结果,则您需要将标志设置为 true
或 re-work您的组件以适应以后的计时。
注意:选择静态选项意味着查询不会找到嵌套在*ngIf
或*ngFor
中的查询结果。
这些结果只能在更改检测 运行 秒后检索。
尝试用 CdkPortalOutlet
查询 ng-template
总是不成功,我不明白为什么?
<ng-template CdkPortalOutlet></ng-template>
@ViewChild(CdkPortalOutlet) test: CdkPortalOutlet;
为了在 AppComponent
模板中使用 CdkPortalOutlet
指令,您必须在 AppModule
中导入 PortalModule
(即已声明 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
因为 Angular 8 @ViewChild
需要提供一个额外的 static
参数,并且很难找到关于将其设置为什么值的文档。如果设置不正确,当尝试使用 @ViewChild
.
CdkPortalOutlet
时,将导致 undefined
值
TLDR
迁移到 Angular 8.
时设置@ViewChild(CdkPortalOutlet, { static: true })
从 Angular 代码中提取注释
如何选择要使用的 static
标志值:true
或 false
?
对于内容查询,我们一直建议在 ngAfterContentInit
中检索查询结果。
这是因为到这个生命周期钩子 运行s 时,相关节点的变化检测已经完成,我们可以保证我们已经收集了所有可能的查询结果。
出于这个原因,大多数应用程序都希望使用 {static: false}
。此设置将确保查询找到依赖于绑定解析的查询匹配项(例如 *ngIf
s 或 *ngFor
s 内的结果)。
如果您需要访问查询中的 TemplateRef
以动态创建视图,则无法在 ngAfterContentInit
中执行此操作。
更改检测已经对该视图进行了 运行,因此使用模板创建新视图将导致抛出 ExpressionHasChangedAfterChecked
错误。
在这种情况下,您需要将 static
标志设置为 true
并在 ngOnInit
中创建您的视图。
在大多数其他情况下,最佳做法是使用 {static: false}
.
但是,为了便于迁移到版本 8,如果您的组件代码已经依赖于某个时间可用的查询结果,您可能还需要将 static
标志设置为 true
之前ngAfterContentInit
。
例如,如果您的组件依赖于在 ngOnInit
挂钩或 @Input
设置器中填充的查询结果,则您需要将标志设置为 true
或 re-work您的组件以适应以后的计时。
注意:选择静态选项意味着查询不会找到嵌套在*ngIf
或*ngFor
中的查询结果。
这些结果只能在更改检测 运行 秒后检索。