マテリアルCDKの新しい Portal を使用して、フォームの複数の部分に動的コンテンツを挿入したいと思います。
私は複雑なフォーム構造を持っていて、目標はサブコンポーネントがテンプレートをインジェクトできる(またはできない)複数の場所を指定するフォームを持つことです。
CDKポータルはこれに最適なソリューションではないでしょうか?
私は何かを試してみましたが、それはやり方ではないと確信しています: https://stackblitz.com/edit/angular-yuz1kg
new ComponentPortal(MyPortalComponent)
でも試しましたが、どうすれば入力を設定できますか?通常、componentRef.component.instance.myInput
カスタムインジェクターを作成し、作成したコンポーネントポータルに注入できます。 -
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);
overlay
はOverlayRef
のインスタンスです(ポータルアウトレットです)
ComponentToPort
内で、作成したインジェクターを注入する必要があります-
@Inject(CONTAINER_DATA) public componentData: any
詳細はこちら-
この方法でコンポーネントの入力を設定(または出力に監視可能としてバインド)できます。
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();
ComponentPortal
の3番目の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);
}
}