对于第二部分,HTML来自Ajax请求,并包含一些必须由angular编译的组件标记.要管理这部分,我使用看起来像这样的指令:
export class ArticleLiveDirective implements OnInit,OnChanges,OnDestroy { // [...] constructor( private container: ViewContainerRef,private compiler: Compiler ) { } // [...] private addHtmlComponent(template: string,properties: any = {}) { this.container.clear(); //Force always rootDomElement. const divTag = document.createElement('div'); divTag.setAttribute('id',this.currentId); divTag.innerHTML = template; template = divTag.outerHTML; // We create dynamic component with injected template @Component({ template }) class ArticleLIveComponent implements OnInit,OnDestroy { constructor( private articleService: ArticleService ) {} ngOnInit() {} ngOnChanges(changes: SimpleChanges) {} ngOnDestroy() {} goToPage($event: Event,pagination: string) { this.articleService.asktochangeArticle(pagination); //Stop propagation $event.stopPropagation(); return false; } } // we declare module with all dependencies @NgModule({ declarations: [ ArticleLIveComponent ],imports: [ BrowserModule,MatTabsModule ],providers: [] }) class ArticleLiveModule {} // we compile it const mod = this.compiler.compileModuleAndAllComponentsSync(ArticleLiveModule); const factory = mod.componentFactories.find((comp) => comp.componentType === ArticleLIveComponent ); // fetch instance of fresh crafted component const component = this.container.createComponent(factory); // we inject parameter. Object.assign(component.instance,properties); } }
正如您所看到的,我可以使用自定义HTML作为模板调用addHtmlComponent方法在运行时编译新组件.
我的模板看起来像:
<div> <h2>Foo bar</h2> <mat-tab-group> <mat-tab label="Tab 1">Content 1</mat-tab> <mat-tab label="Tab 2">Content 2</mat-tab> </mat-tab-group> <p>Other content</p>
一切顺利,直到我切换到AOT编译(我使用:https://github.com/angular/angular-cli/tree/master/packages/%40ngtools/webpack)
可能的原因:
我猜的主要原因是因为AOT编译从输出编译的bundle中删除Angular的“编译器”部分.
我尝试了什么
– 我试图直接在我的代码上要求它但仍然不存在.
– 我试着检查像角度(或角度材料)的网站如何处理它.但是不符合我的情况.实际上,两者都已经在AOT版本中编译了所有示例的版本.动态部分是样本周围的“正义”内容.
如果要检查角度材料的作用:
每个组件的所有网站示例:https://github.com/angular/material2/tree/master/src/material-examples
可能是正确的方法,但我不知道如何适应它来管理,动态Tab内容.
编辑:我在这里添加样品:https://github.com/yanis-git/aot-jit-angular(分店大师)
正如您将看到的,AOT编译从bundle中删除了wall编译器,结果如下:
Module not found: Error: Can't resolve '@angular/compiler/src/config'
我试图在AppModule上强制compilater Factory,但仍然没有结果.
我在同一个repo上有另一个示例,但在分支“lazy-jit”上,现在我将Compiler嵌入到输出的包中,但是新的错误出现在我面前:
ERROR Error: No NgModule Metadata found for 'ArticleLiveModule'.
谁看起来与这个问题完全相同:https://github.com/angular/angular/issues/16033
import { Compiler,COMPILER_OPTIONS,CompilerFactory,NgModule } from '@angular/core'; import { BrowserModule,} from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; import { HelloComponent } from './hello.component'; import { JitCompilerFactory } from '@angular/platform-browser-dynamic'; export function createCompiler(compilerFactory: CompilerFactory) { return compilerFactory.createCompiler(); } @NgModule({ providers: [ { provide: COMPILER_OPTIONS,useValue: {},multi: true },{ provide: CompilerFactory,useClass: JitCompilerFactory,deps: [COMPILER_OPTIONS] },{ provide: Compiler,useFactory: createCompiler,deps: [CompilerFactory] } ],imports: [BrowserModule,FormsModule],declarations: [AppComponent,HelloComponent],bootstrap: [AppComponent] }) export class AppModule { }
But JitCompiler still not able to create Dependency Injection tree. I
suspect @Injectable to be remove from AOT part. But i can’t do your
trick.
在上面的代码示例中,没有NgModule和Component的装饰器.所以,这意味着没有@Injectable也无法注入提供者.那么为什么我们不为@NgModule和@Component @Injectable装饰器编写并只将其写入服务?
因为,他们有装饰器(@ NgModule / @ Components),服务没有.他们的装饰者足以让Angular知道他们是可注射的.
CODE EXAMPLE与DI.
更新:
创建自定义包装器CustomNgModule,CustomComponent和CustomInjectable装饰器:
export function CustomComponent(annotation: any) { return function (target: Function) { const component = new Component(annotation); Component(component)(target); }; } export function CustomNgModule(annotation: any) { return function (target: Function) { const ngModule = new NgModule(annotation); NgModule(ngModule)(target); }; } export function CustomInjectable() { return function (target: Function) { const injectable = new Injectable(); Injectable()(target); }; }
When building with
AOT
flag,Angular-CLI looks like cleans bundle
from native decorators from parts of code which need to be compiled
dynamically.And where you want
dynamically
@H_301_76@ compile modules with components
inAOT
withDI
functionality,replace native decorators
(NgModule/Injectable...
) with custom one to preserve decorators in
AOT
compilation mode:
lazy.module.ts:
@CustomComponent({ selector: 'lazy-component',template: 'Lazy-loaded component. name: {{name}}.Service {{service.foo()}}!',//providers: [SampleService] }) export class LazyComponent { name; constructor(public service: SampleService) { console.log(service); console.log(service.foo()); } } @CustomNgModule({ declarations: [LazyComponent],providers: [SampleService] }) export class LazyModule { }
app.component.ts:
... ngAfterViewInit() { this.compiler.compileModuleAndAllComponentsAsync(LazyModule) .then((factories) => { const f = factories.componentFactories[0]; const cmpRef = this.vc.createComponent(f); cmpRef.instance.name = 'dynamic'; }); } ...