Je voudrais utiliser le nouveau Portal from material CDK pour injecter du contenu dynamique dans plusieurs parties d’un formulaire.
J'ai une structure de formulaire complexe et le but est d'avoir un formulaire qui spécifie plusieurs endroits où les sous-composants peuvent (ou non) injecter des modèles.
Peut-être que le portail CDK n’est pas la meilleure solution pour cela?
J'ai essayé quelque chose mais je suis sûr que ce n'est pas la façon de faire: https://stackblitz.com/edit/angular-yuz1kg
J'ai essayé aussi avec new ComponentPortal(MyPortalComponent)
mais comment pouvons-nous définir des entrées sur elle? Est généralement quelque chose comme componentRef.component.instance.myInput
Vous pouvez créer un injecteur personnalisé et l'injecter dans le portail de composants que vous créez. -
createInjector(dataToPass): PortalInjector {
const injectorTokens = new WeakMap();
injectorTokens.set(CONTAINER_DATA, dataToPass);
return new PortalInjector(this._injector, injectorTokens);
}
CONTAINER_DATA est un injecteur personnalisé (InjectorToken) créé par -
export const CONTAINER_DATA = new InjectionToken<{}>('CONTAINER_DATA');
Pour consommer l'injecteur créé, utilisez -
let containerPortal = new ComponentPortal(ComponentToPort, null, this.createInjector({
data1,
data2
}));
overlay.attach(containerPortal);
overlay est une instance de OverlayRef (qui est Portal Outlet)
Dans "ComponentToPort", vous devrez injecter l’injecteur créé -
@Inject(CONTAINER_DATA) public componentData: any
Plus sur ceci ici -
Vous pouvez injecter des données dans ComponentPortal avec un injecteur spécifique transmis au 3ème paramètre de ComponentPortal (problème de syntaxe résolu: impossible de résoudre tous les paramètres pour Component: ([objet Object], [objet Objet],?).
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);
}
}
Peut définir les entrées de composant (ou se lier aux sorties comme observable) de cette manière
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();