【问题标题】:Angular Dynamic Component Based on HTTP call基于 HTTP 调用的 Angular 动态组件
【发布时间】:2019-02-19 11:06:49
【问题描述】:

动态创建组件模板和 Typescript 代码。

我正在尝试动态生成组件,HTTP 服务调用向我们发送 HTML 模板和 Typescript 代码。在这里,我们能够动态设置 HTMl 模板,但不能动态设置 typescript 代码,无法弄清楚如何动态设置 typescript 代码。

* 请在下面找到基于 HTTP 调用呈现 HTML 模板的代码。 *

import { HttpClient, HttpClientModule } from "@angular/common/http";
import { Component, ViewChild, ViewContainerRef, Compiler, Injector, NgModule, NgModuleRef, ComponentFactoryResolver, OnInit } from "@angular/core";

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

  @ViewChild('vc', { read: ViewContainerRef }) _container: ViewContainerRef;

  constructor(private http: HttpClient, private _compiler: Compiler, private componentFactoryResolver: ComponentFactoryResolver,
    private _injector: Injector,
    private _m: NgModuleRef<any>) {

  }
  ngOnInit() {
    return this.http.get("https://raw.githubusercontent.com/ketan-gote/stackblitz-demo/master/template.txt", { responseType: 'text' }).subscribe((txt: any) => {
      console.log(txt);
      const tmpCmp = Component({ template: txt, selector: 'abcd' })(class {

      });
      const tmpModule = NgModule({ imports: [HttpClientModule], declarations: [tmpCmp], entryComponents: [tmpCmp] })(class {
      });

      this._compiler.compileModuleAsync(tmpModule)
        .then((moduleFactory) => {
          debugger;
          const resolver = moduleFactory.create(this._injector).componentFactoryResolver;
          const f = resolver.resolveComponentFactory(tmpCmp);
          const cmpRef = f.create(this._injector, [], null, this._m);
          this._container.insert(cmpRef.hostView);
        })
    });

  }
}

这里是a working link

* 问题 现在,当我们尝试获取 TS 代码作为响应的一部分时,它会给出错误 core.js:12501 ERROR TypeError: Cannot read property '__annotations__' of undefined *

请在下面找到呈现 TS 的代码


import { HttpClient, HttpClientModule } from "@angular/common/http";
import { Component, ViewChild, ViewContainerRef, Compiler, Injector, NgModule, NgModuleRef, ComponentFactoryResolver, OnInit } from "@angular/core";

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

  @ViewChild('vc', { read: ViewContainerRef }) _container: ViewContainerRef;

  constructor(private http: HttpClient, private _compiler: Compiler, private componentFactoryResolver: ComponentFactoryResolver,
    private _injector: Injector,
    private _m: NgModuleRef<any>) {

  }
  ngOnInit() {
    return this.http.get("https://raw.githubusercontent.com/ketan-gote/stackblitz-demo/master/ts.txt", { responseType: 'text' }).subscribe((txt: any) => {
      console.log(txt);
      const tmpCmp = Component({ template: "<h1>HEAD</h1>", selector: 'abcd' })(txt);
      const tmpModule = NgModule({ imports: [HttpClientModule], declarations: [tmpCmp], entryComponents: [tmpCmp] })(class {
      });

      this._compiler.compileModuleAsync(tmpModule)
        .then((moduleFactory) => {
          debugger;
          const resolver = moduleFactory.create(this._injector).componentFactoryResolver;
          const f = resolver.resolveComponentFactory(tmpCmp);
          const cmpRef = f.create(this._injector, [], null, this._m);
          this._container.insert(cmpRef.hostView);
        })
    });

  }
}

这里是is not working code link

【问题讨论】:

    标签: angular


    【解决方案1】:

    我知道已经很晚了,但这可以通过 'eval' 函数来完成。

    从此改行

    const tmpCmp = Component({ template: "<h1>HEAD</h1>", selector: 'abcd' })(txt);
    

    到这里

    const tmpCmp = Component({ template: "<h1>HEAD</h1>", selector: 'abcd' })(eval('(' +txt+ ')'));
    

    我在这篇文章 (https://stackoverflow.com/a/14377840) 中找到了答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-22
      • 2023-03-15
      • 2019-07-28
      • 1970-01-01
      • 2017-11-24
      • 1970-01-01
      • 2021-07-25
      • 1970-01-01
      相关资源
      最近更新 更多