J'ai trouvé le code suivant pour générer des composants à la volée à partir d'une chaîne (angular2 génère un composant à partir d'un string) et a créé une compileBoundHtml directive qui transmet les données d'entrée (ne gère pas les résultats, mais je pense que la même stratégie s'appliquerait ainsi, vous pourriez modifier cette):
@Directive({selector: '[compileBoundHtml]', exportAs: 'compileBoundHtmlDirective'})
export class CompileBoundHtmlDirective {
// input must be same as selector so it can be named as property on the DOM element it's on
@Input() compileBoundHtml: string;
@Input() inputs?: {[x: string]: any};
// keep reference to temp component (created below) so it can be garbage collected
protected cmpRef: ComponentRef<any>;
constructor( private vc: ViewContainerRef,
private compiler: Compiler,
private injector: Injector,
private m: NgModuleRef<any>) {
this.cmpRef = undefined;
}
/**
* Compile new temporary component using input string as template,
* and then insert adjacently into directive's viewContainerRef
*/
ngOnChanges() {
class TmpClass {
[x: string]: any;
}
// create component and module temps
const tmpCmp = Component({template: this.compileBoundHtml})(TmpClass);
// note: switch to using annotations here so coverage sees this function
@NgModule({imports: [/*your modules that have directives/components on them need to be passed here, potential for circular references unfortunately*/], declarations: [tmpCmp]})
class TmpModule {};
this.compiler.compileModuleAndAllComponentsAsync(TmpModule)
.then((factories) => {
// create and insert component (from the only compiled component factory) into the container view
const f = factories.componentFactories[0];
this.cmpRef = f.create(this.injector, [], null, this.m);
Object.assign(this.cmpRef.instance, this.inputs);
this.vc.insert(this.cmpRef.hostView);
});
}
/**
* Destroy temporary component when directive is destroyed
*/
ngOnDestroy() {
if (this.cmpRef) {
this.cmpRef.destroy();
}
}
}
La modification importante est l'ajout de:
Object.assign(this.cmpRef.instance, this.inputs);
Fondamentalement, il copie les valeurs que vous voulez être sur le nouveau composant dans le tmp de classe de composant, de sorte qu'ils peuvent être utilisés dans les composants générés.
Il peut être utilisé comme:
<div [compileBoundHtml]="someContentThatHasComponentHtmlInIt" [inputs]="{anInput: anInputValue}"></div>
J'espère que cela sauve quelqu'un de la quantité massive de Googler que j'avais à faire.