Angular2.0+动态绑定html文本

背景:

Angular2项目网站需要一个容器页面,可以展示用户自定义开发的html文本(包含css,js,html等)

如下图,编辑好css,js及html后,在右侧可以实时查看展示效果,并且可以执行按钮事件。

思路:

      定义一个通用组件容器接受js,css参数,组件中template对象加载html,styles对象加载css,并通过Renderer类注入js脚本。

 

实现:

1.创建树组件  dynamic-com.component.ts

import { Component, OnInit, Input, NgModule, ElementRef } from '@angular/core';
import { SharedModule } from '../../../module/shared-module/shared-module';
import { Renderer2, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';

@Component({
  selector: 'app-dynamic-com',
  template: `
    <ng-container *ngComponentOutlet="dynamicComponent; ngModuleFactory: dynamicModule;">
    </ng-container>`,
  styleUrls: ['./dynamic-com.component.css']
})
export class DynamicComComponent implements OnInit {
  dynamicComponent: any;
  dynamicModule: NgModuleFactory<any>;
  @Input('html') html: string;  //接收html

  @Input('js') js: string;  

  @Input('css') css: string;

  @Input('dataSource') dataSource: any;  //html中需要绑定的数据源

  constructor(private compiler: Compiler) { }

  //改变后重新编译生成html
  ngOnChanges(changes: SimpleChanges) {
    if (changes['html'] && !changes['html'].isFirstChange() ||
      changes['css'] && !changes['css'].isFirstChange() ||
      changes['js'] && !changes['js'].isFirstChange() ||
      (changes['dataSource'] && !changes['dataSource'].isFirstChange())) {
      this.dynamicComponent = this.createNewComponent(this.html, this.dataSource);
        this.dynamicModule = this.compiler.compileModuleSync(this.createComponentModule(this.dynamicComponent));
    }
  }

  ngOnInit() {
    this.dynamicComponent = this.createNewComponent(this.html, this.dataSource);
    this.dynamicModule = this.compiler.compileModuleSync(this.createComponentModule(this.dynamicComponent));
  }

  protected createComponentModule(componentType: any) {
    @NgModule({
      imports: [SharedModule],
      declarations: [
        componentType
      ],
      entryComponents: [componentType]
      })
    class RuntimeComponentModule {
    }

    // a module for just this Type
    return RuntimeComponentModule;
  }

  protected createNewComponent(template: string, dataSource: any) {
    console.log(this.js + template);
    let comJs = this.js;
    let comCss = this.css;

    @Component({
      selector: 'dynamic-component',
      template: template ? template : '<div></div>',
      styles: [comCss]
    })
    class MyDynamicComponent {
      public list: any = dataSource;

    constructor(private _renderer2: Renderer2,
      @Inject(DOCUMENT) private _document,
      private elementRef: ElementRef) {
    }
    //注入js
    ngAfterViewInit() {
      if (comJs) {
        var s = document.createElement("script");
        s.type = "text/javascript";
        //s.src = "http://";
        //s.text = `function test(){alert(111);}`;
        s.text = comJs;
        this.elementRef.nativeElement.appendChild(s);
      }
    }
  }

  return MyDynamicComponent;
  }
}

 

2.引入组件 

form-design.component.html

可以通过<app-dynamic-com [js]="js" [css]="css" [html]="html" [dataSource]="list"></app-dynamic-com>来引入组件

<div style="margin: 0 auto;text-align: left;border: 1px solid #c5c5c5;">
<div id="CodeArea" style="float: left; height: 435px; width: 50%;margin-left: 5px;border-right: 1px solid #cfcfe6;">
  <h2>编辑您的代码:</h2>
  <div style="width:45%;float:left;">
  <h4>css:</h4>
  <textarea [(ngModel)]="css"></textarea>
</div>
<div style="width:45%;float:left;">
  <h4>js:</h4>
  <textarea [(ngModel)]="js"></textarea>
</div>
<div style="width:100%;float:left;">
  <h4>html:</h4>
  <textarea [(ngModel)]="html"></textarea>
</div>

</div>

<div id="result" style="float: left; height: 435px;width: 49%;">
  <h2>查看结果:</h2>
  <br />
  <app-dynamic-com [js]="js" [css]="css" [html]="html" [dataSource]="dataSource"></app-dynamic-com>
</div>
</div>

 

3. form-design.component.ts组件类定义参数

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-form-design',
  templateUrl: './form-design.component.html',
  styleUrls: ['./form-design.component.css']
})
export class FormDesignComponent implements OnInit {

  dataSource: Array<any> = [];
  css=`.myDiv{ font-size:20px}
      #div1{color:red}`;
  js=` function test(){
      alert(111)
     }`;
  html = `<div class="myDiv">按钮:<button onclick="test()">查看</button><br/>
        <div id="div1">文字</div></div>`;
 
  constructor(private listService: ListService) {
  }

  ngOnInit() {}
}

 

 

 
posted @ 2018-03-27 15:19  齐大齐  阅读(5805)  评论(0编辑  收藏  举报