web-dev-qa-db-ja.com

Angular CDK:ComponentPortalで入力を設定する方法

マテリアルCDKの新しい Portal を使用して、フォームの複数の部分に動的コンテンツを挿入したいと思います。

私は複雑なフォーム構造を持っていて、目標はサブコンポーネントがテンプレートをインジェクトでき​​る(またはできない)複数の場所を指定するフォームを持つことです。

CDKポータルはこれに最適なソリューションではないでしょうか?

私は何かを試してみましたが、それはやり方ではないと確信しています: https://stackblitz.com/edit/angular-yuz1kg

new ComponentPortal(MyPortalComponent)でも試しましたが、どうすれば入力を設定できますか?通常、componentRef.component.instance.myInput

21
JoG

カスタムインジェクターを作成し、作成したコンポーネントポータルに注入できます。 -

createInjector(dataToPass): PortalInjector {
    const injectorTokens = new WeakMap();
    injectorTokens.set(CONTAINER_DATA, dataToPass);
    return new PortalInjector(this._injector, injectorTokens);
}

CONTAINER_DATAは-によって作成されたカスタムインジェクター(InjectorToken)です-

export const CONTAINER_DATA = new InjectionToken<{}>('CONTAINER_DATA');

作成したインジェクターを使用するには、次を使用します-

let containerPortal = new ComponentPortal(ComponentToPort, null, this.createInjector({
          data1,
          data2
        }));

overlay.attach(containerPortal);

overlayOverlayRefのインスタンスです(ポータルアウトレットです)

ComponentToPort内で、作成したインジェクターを注入する必要があります-

@Inject(CONTAINER_DATA) public componentData: any

詳細はこちら-

  1. https://github.com/angular/material2/issues/8322

  2. https://github.com/angular/material2/issues/8322

22
Awadhoot

この方法でコンポーネントの入力を設定(または出力に監視可能としてバインド)できます。

portal = new ComponentPortal(MyComponent);
this.portalHost = new DomPortalHost(
      this.elementRef.nativeElement,
      this.componentFactoryResolver,
      this.appRef,
      this.injector
    );

const componentRef = this.portalHost.attach(this.portal);
componentRef.instance.myInput = data;
componentRef.instance.myOutput.subscribe(...);
componentRef.changeDetectorRef.detectChanges();
8
Karlos1337

ComponentPortal3番目のparamを渡した特定のインジェクターを使用して、ComponentPortalにデータを注入できます。

構文の問題を修正

Can't resolve all parameters for Component: ([object Object], [object Object], ?

これはコードです

export const PORTAL_DATA = new InjectionToken<{}>('PortalData');

class ContainerComponent {
  constructor(private injector: Injector, private overlay: Overlay) {}

  attachPortal() {
    const componentPortal = new ComponentPortal(
      ComponentToPort,
      null,
      this.createInjector({id: 'first-data'})
    );
    this.overlay.create().attach(componentPortal);
  }

  private createInjector(data): PortalInjector {

    const injectorTokens = new WeakMap<any, any>([
      [PORTAL_DATA, data],
    ]);

    return new PortalInjector(this.injector, injectorTokens);
  }
}

class ComponentToPort {
  constructor(@Inject(PORTAL_DATA) public data ) {
    console.log(data);
  }
}
8
domen