Angular 7 CDK 门户:错误必须提供要附加的门户
Angular 7 CDK Portal : Error Must provide a portal to attach
我有这个 ActionButtonComponent,它使用 Angular CDK 门户:
import { CdkPortal, DomPortalHost } from '@angular/cdk/portal';
import { AfterViewInit, ApplicationRef, Component, ComponentFactoryResolver, Injector, OnDestroy, ViewChild } from '@angular/core';
@Component({
selector: 'app-action-button',
template: `
<ng-container *cdkPortal>
<ng-content></ng-content>
</ng-container>
`
})
export class ActionButtonComponent implements AfterViewInit, OnDestroy {
@ViewChild(CdkPortal)
private portal: CdkPortal;
private host: DomPortalHost;
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
private applicationRef: ApplicationRef,
private injector: Injector
) { }
ngAfterViewInit(): void {
this.host = new DomPortalHost(
document.querySelector('#action'),
this.componentFactoryResolver,
this.applicationRef,
this.injector
);
console.log(this.portal); // <-- logs "undefined"
console.log(document.querySelector('#action')); // <-- logs "<div id="action"></div>"
this.host.attach(this.portal);
}
ngOnDestroy(): void {
this.host.detach();
}
}
我像这样在另一个组件中使用它:
<div id="action"></div>
<!-- ... other code here ... -->
<router-outlet></router-outlet>
最后,这是来自进入路由器出口的组件:
<app-action-button>
<button>click</button>
</app-action-button>
在“ngAfterViewInit”中,我记录了门户变量和“document.querySelector('#action')”。门户变量是“未定义的”,但组件找到了带有 id="#action" 的 div。
当我 运行 它时,我得到这个错误:
Error: Must provide a portal to attach
at throwNullPortalError (portal.es5.js:22)
at DomPortalOutlet.push../node_modules/@angular/cdk/esm5/portal.es5.js.BasePortalOutlet.attach (portal.es5.js:286)
at action-button.component.ts:36
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:16147)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)
at push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask (zone.js:496)
at ZoneTask.invoke (zone.js:485)
at timer (zone.js:2054)
为什么变量是“portal”
@ViewChild(CdkPortal)
private portal: CdkPortal;
“ngAfterViewInit()”中仍未定义?
模板中是否使用cdkPortal
<ng-container *cdkPortal>
<ng-content></ng-content>
</ng-container>
错了?
注意:在 app.module.ts 中,将 ActionButtonComponent 添加到 entryComponents 数组没有任何效果:
@NgModule({
entryComponents: [ActionButtonComponent],
declarations: [...]
可以找到 Stackblitz here
Angular CLI: 7.1.4
Node: 11.5.0
OS: linux x64
Angular: 7.1.4
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.11.4
@angular-devkit/build-angular 0.11.4
@angular-devkit/build-optimizer 0.11.4
@angular-devkit/build-webpack 0.11.4
@angular-devkit/core 7.1.4
@angular-devkit/schematics 7.1.4
@angular/cdk 7.2.0
@ngtools/webpack 7.1.4
@schematics/angular 7.1.4
@schematics/update 0.11.4
rxjs 6.3.3
typescript 3.1.6
webpack 4.23.1
我检查了你的 Stackblitz。
您忘记在 app.module.ts 中导入 PortalModule。
import {PortalModule} from '@angular/cdk/portal';
...
@NgModule({
...
declarations: [ ... ],
imports: [
...
PortalModule
],
...
})
export class AppModule { }
我实现了同样的例子。它现在应该可以工作了。
我有这个 ActionButtonComponent,它使用 Angular CDK 门户:
import { CdkPortal, DomPortalHost } from '@angular/cdk/portal';
import { AfterViewInit, ApplicationRef, Component, ComponentFactoryResolver, Injector, OnDestroy, ViewChild } from '@angular/core';
@Component({
selector: 'app-action-button',
template: `
<ng-container *cdkPortal>
<ng-content></ng-content>
</ng-container>
`
})
export class ActionButtonComponent implements AfterViewInit, OnDestroy {
@ViewChild(CdkPortal)
private portal: CdkPortal;
private host: DomPortalHost;
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
private applicationRef: ApplicationRef,
private injector: Injector
) { }
ngAfterViewInit(): void {
this.host = new DomPortalHost(
document.querySelector('#action'),
this.componentFactoryResolver,
this.applicationRef,
this.injector
);
console.log(this.portal); // <-- logs "undefined"
console.log(document.querySelector('#action')); // <-- logs "<div id="action"></div>"
this.host.attach(this.portal);
}
ngOnDestroy(): void {
this.host.detach();
}
}
我像这样在另一个组件中使用它:
<div id="action"></div>
<!-- ... other code here ... -->
<router-outlet></router-outlet>
最后,这是来自进入路由器出口的组件:
<app-action-button>
<button>click</button>
</app-action-button>
在“ngAfterViewInit”中,我记录了门户变量和“document.querySelector('#action')”。门户变量是“未定义的”,但组件找到了带有 id="#action" 的 div。
当我 运行 它时,我得到这个错误:
Error: Must provide a portal to attach
at throwNullPortalError (portal.es5.js:22)
at DomPortalOutlet.push../node_modules/@angular/cdk/esm5/portal.es5.js.BasePortalOutlet.attach (portal.es5.js:286)
at action-button.component.ts:36
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:16147)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)
at push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask (zone.js:496)
at ZoneTask.invoke (zone.js:485)
at timer (zone.js:2054)
为什么变量是“portal”
@ViewChild(CdkPortal)
private portal: CdkPortal;
“ngAfterViewInit()”中仍未定义?
模板中是否使用cdkPortal
<ng-container *cdkPortal>
<ng-content></ng-content>
</ng-container>
错了?
注意:在 app.module.ts 中,将 ActionButtonComponent 添加到 entryComponents 数组没有任何效果:
@NgModule({
entryComponents: [ActionButtonComponent],
declarations: [...]
可以找到 Stackblitz here
Angular CLI: 7.1.4
Node: 11.5.0
OS: linux x64
Angular: 7.1.4
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.11.4
@angular-devkit/build-angular 0.11.4
@angular-devkit/build-optimizer 0.11.4
@angular-devkit/build-webpack 0.11.4
@angular-devkit/core 7.1.4
@angular-devkit/schematics 7.1.4
@angular/cdk 7.2.0
@ngtools/webpack 7.1.4
@schematics/angular 7.1.4
@schematics/update 0.11.4
rxjs 6.3.3
typescript 3.1.6
webpack 4.23.1
我检查了你的 Stackblitz。
您忘记在 app.module.ts 中导入 PortalModule。
import {PortalModule} from '@angular/cdk/portal';
...
@NgModule({
...
declarations: [ ... ],
imports: [
...
PortalModule
],
...
})
export class AppModule { }
我实现了同样的例子。它现在应该可以工作了。