Нашел в интернетах код директивы для динамического создания компонентов, в ней используются
Compiler:compileModuleAndAllComponentsAsync,
ViewContainerRef:createComponent и прочие страшные слова:
compile.directive.tsimport {
Compiler, NgModule, Component, Input, ComponentRef, Directive,
ModuleWithComponentFactories, OnChanges, Type,
ViewContainerRef
} from '@angular/core';
import { CommonModule } from '@angular/common';
@Directive({
selector: '[compile]'
})
export class CompileDirective implements OnChanges {
@Input() compile: string;
@Input() compileContext: any;
compRef: ComponentRef<any>;
constructor(private vcRef: ViewContainerRef, private compiler: Compiler) {}
ngOnChanges() {
if(!this.compile) {
if(this.compRef) {
this.updateProperties();
return;
}
throw Error('You forgot to provide template');
}
this.vcRef.clear();
this.compRef = null;
const component = this.createDynamicComponent(this.compile);
const module = this.createDynamicModule(component);
this.compiler.compileModuleAndAllComponentsAsync(module)
.then((moduleWithFactories: ModuleWithComponentFactories<any>) => {
let compFactory = moduleWithFactories.componentFactories.find(x => x.componentType === component);
this.compRef = this.vcRef.createComponent(compFactory);
this.updateProperties();
})
.catch(error => {
console.log(error);
});
}
updateProperties() {
for(var prop in this.compileContext) {
this.compRef.instance[prop] = this.compileContext[prop];
}
}
private createDynamicComponent (template:string) {
@Component({
selector: 'custom-dynamic-component',
template: template,
})
class CustomDynamicComponent {}
return CustomDynamicComponent;
}
private createDynamicModule (component: Type<any>) {
@NgModule({
// You might need other modules, providers, etc...
// Note that whatever components you want to be able
// to render dynamically must be known to this module
imports: [CommonModule],
declarations: [component]
})
class DynamicModule {}
return DynamicModule;
}
}
Используется она как-то так:
// Шаблон компонента
<ng-container *compile="template; context: { some_key: true }"></ng-container>
// Объявление свойства template в текущем компоненте
template = `
<div *ngIf="some_key">This shit finally works, nice</div>
`;
При выполнении этого чуда в текущем компоненте будет успешно отрендерен
<div>This shit finally works, nice</div>
.
Основной вопрос: как передать объект чтобы он использовался в качестве
compileContext? Ну или чтобы объект был передан как свойство
compileContext
И было бы вообще прекрасно если бы была прояснена парочка непонятных для меня моментов:
1. Почему эта директива структурная?
2. Как вообще мапится
context на
compileContext? Какой механизм обрабатывает строку
"template; context: { some_key: true }"?
Заранее спасибо!
Небольшой апдейт: речь не об AOT, а именно о JIT.