Портал Angular 7 CDK: Ошибка Должен предоставить портал для подключения - PullRequest
0 голосов
/ 30 декабря 2018

У меня есть этот ActionButtonComponent, который использует Angular CDK Portal:

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')".Переменная портала "undefined", но компонент находит div с id = "# action".

Когда я запускаю его, я получаю эту ошибку:

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)

Почему переменная "портал "

@ViewChild(CdkPortal)
private portal: CdkPortal;

все еще не определен в" ngAfterViewInit () "?

Использовать ли в шаблоне cdkPortal

<ng-container *cdkPortal>
  <ng-content></ng-content>
</ng-wrong?er>

неправильно?

Примечание: в app.module.ts добавление ActionButtonComponent в массив entryComponents не оказывает никакого влияния:

@NgModule({
    entryComponents: [ActionButtonComponent],
    declarations: [...]

Здесь можно найти Stackblitz

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

1 Ответ

0 голосов
/ 07 марта 2019

Я проверил ваш Stackblitz.

Вы забыли импортировать PortalModule в ваш app.module.ts.

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

@NgModule({
  ...

  declarations: [ ... ],
  imports: [
     ...
     PortalModule
  ],

  ...

})
export class AppModule { }

Я реализовал тот же пример.Это должно работать сейчас.

...