Angular动态编译HTML模版

问题:需要打印的模版特别多,而且各不相同,可能需要经常改动,如果在前端进行单独创建组件的方式每次添加模版修改模版都要重新发布版本。

解决方式:通过把模版HTML保存到数据库的方式,根据调用打印的传参获取不同的打印模版

oracle中nvarchar最多存4000个字符数量 NCLOB最大存储大小为4gb

通过[innerHtml],只能渲染模版中的html语法和样式,模版中的angular模版无法这些无法进行解析。这种方式只能渲染文本内容

通过ComponentFactoryResolver,这个对象可以接受一个组件类型创建一个组件实例。这种方式组件在前端需要存在

通过下面这种方式来动态编译HTML模版

import {Compiler, Component, ComponentRef, Injector, NgModule, NgModuleRef, ViewChild, ViewContainerRef} from "@angular/core";
import {CommonModule} from "@angular/common";
import {RouterModule} from "@angular/router";
import { HelloComponent } from "./hello.component";

@Component({
  selector: 'dynamic-template',
  template: `<h2>Stuff bellow will get dynamically created and injected<h2>
          <div #vc></div>`
})
export class DynamicTemplateComponent {
  @ViewChild('vc', {read: ViewContainerRef}) vc: ViewContainerRef;

  private cmpRef: ComponentRef<any>;

  constructor(private compiler: Compiler,
              private injector: Injector,
              private moduleRef: NgModuleRef<any>,
  ) {}

  ngAfterViewInit() {
    this.createComponentFromRaw(`<div >
    <div>Start Raw Component ... </div> 
    <h5>Binding value: {{data.some}}</h5> 
    <span *ngIf="getX() === 'X'">Use *ngIf: {{getX()}} </span>
    </div>`);
  }

  private createComponentFromRaw(template: string) {
    const styles = [];
    function TmpCmpConstructor() {
      //需要给当前创建的模版传递的数据
      this.data = { some: 'data' };
      //需要给当前创建的模版传递的方法
      this.getX = () => 'X';
    }
    const tmpCmp = Component({ template, styles })(new TmpCmpConstructor().constructor);

    // Now, also create a dynamic module.
    const tmpModule = NgModule({
      imports: [CommonModule],
      declarations: [tmpCmp],
      //如果这个html模版中用到了其他组件  需要把这个组件也传递进去
      // declarations: [tmpCmp, HelloComponent],
      // providers: [] - e.g. if your dynamic component needs any service, provide it here.
    })(class {});

    // Now compile this module and component, and inject it into that #vc in your current component template.
    this.compiler.compileModuleAndAllComponentsAsync(tmpModule)
        .then((factories) => {
          const f = factories.componentFactories[0];
          this.cmpRef = f.create(this.injector, [], null, this.moduleRef);
          this.cmpRef.instance.name = 'my-dynamic-component';
          this.vc.insert(this.cmpRef.hostView);
        });
  }

  // Cleanup properly. You can add more cleanup-related stuff here.
  ngOnDestroy() {
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }
  }
}

资料

https://stackblitz.com/edit/dynamic-raw-template?file=src%2Fapp%2Fdynamic-template.component.ts

https://stackoverflow.com/questions/48028676/compile-dynamic-html-in-angular-4-5-something-similar-to-compile-in-angular-js