You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular基于HTTP动态生成组件:TypeScript代码加载问题求助

解决Angular动态加载远程TypeScript组件时__annotations__未定义的错误

Hey, I see exactly what's going wrong here. That TypeError: Cannot read property '__annotations__' of undefined error pops up because you're passing a raw TypeScript string directly to Angular's Component decorator—and that decorator expects a real class constructor, not plain text.

Let's break down the problematic line in your code:

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

Here, txt is just a string of TS code you fetched from the server (like class MyDynamicComponent { ... }). It's not a parsed, executable class object yet. Angular's decorator tries to attach metadata to this string, but since strings don't have properties like __annotations__, it throws that error.

Fixing the Issue

To load a remote TS component successfully, you need to turn that string into a usable class first. Here's a step-by-step solution:

  1. Compile TS to JS (skip this if you fetch pre-compiled JS directly)
  2. Execute the JS code to get the component class constructor
  3. Apply Angular's decorators and compile the component normally

Here's the updated code that works:

import { HttpClient, HttpClientModule } from "@angular/common/http";
import { Component, ViewChild, ViewContainerRef, Compiler, Injector, NgModule, NgModuleRef, OnInit } from "@angular/core";
// Import TypeScript library if you need to compile TS in the browser
import * as ts from 'typescript';

@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 _injector: Injector, 
    private _m: NgModuleRef<any>
  ) { }

  ngOnInit() {
    this.http.get("https://raw.githubusercontent.com/ketan-gote/stackblitz-demo/master/ts.txt", { responseType: 'text' })
      .subscribe((tsCode: string) => {
        // Step 1: Transpile TS to JS (skip if fetching pre-compiled JS)
        const jsCode = ts.transpileModule(tsCode, {
          compilerOptions: {
            module: ts.ModuleKind.ES2020,
            target: ts.ScriptTarget.ES2020,
            emitDecoratorMetadata: true,
            experimentalDecorators: true
          }
        }).outputText;

        // Step 2: Execute the JS to get the component class
        // Ensure your remote code defines a class named DynamicComponent
        const getComponentClass = new Function(`${jsCode}; return DynamicComponent;`);
        const dynamicComponentClass = getComponentClass();

        // Step 3: Apply Angular's Component decorator
        const tmpCmp = Component({
          // You can also fetch the template from remote here if needed
          template: "<h1>HEAD</h1>", 
          selector: 'abcd'
        })(dynamicComponentClass);

        // Create a temporary module for the component
        const tmpModule = NgModule({ 
          imports: [HttpClientModule], 
          declarations: [tmpCmp],
          entryComponents: [tmpCmp] // Optional for Angular 9+, but safe to keep for compatibility
        })(class { });

        // Compile and render the component
        this._compiler.compileModuleAsync(tmpModule)
          .then((moduleFactory) => {
            const moduleRef = moduleFactory.create(this._injector);
            const resolver = moduleRef.componentFactoryResolver;
            const cmpFactory = resolver.resolveComponentFactory(tmpCmp);
            const cmpRef = cmpFactory.create(this._injector, [], null, this._m);
            this._container.insert(cmpRef.hostView);
          })
          .catch(err => console.error("Failed to load dynamic component:", err));
      });
  }
}

Important Notes

  • Security Warning: Using new Function to execute remote code carries XSS risks. Only load code from trusted sources to avoid malicious injections.
  • Angular Production Mode: JIT compilation is disabled by default in production. If you need this to work in prod, you'll need to enable JIT or adjust your build configuration to allow dynamic compilation.
  • Remote Code Structure: Make sure your remote TS/JS code defines a class (like DynamicComponent) that matches what you're trying to return in the new Function block.

内容的提问来源于stack exchange,提问作者ketan gote

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 03:58:38