首页 文章

Angular 2 RuntimeCompiler:未提供XHR实现

提问于
浏览
1

我正在尝试使用RuntimeCompiler使Angular 2动态编译HTML片段 . 我在post找到了解决方案(参见 Angular 2.0 RC 5 related 回答),直到我在组件的装饰器中使用templateUrl而不是内联模板 .

@Component({
  selector: 'dynamic-detail',
  providers: [DynamicTypeBuilder, DynamicTemplateBuilder],
  templateUrl: 'app/dynamic/detail.view.html',
})

当我使用templateUrl时,我收到以下错误:

Unhandled Promise rejection: EXCEPTION: Error in ./AppComponent class AppComponent - inline template:4:3
ORIGINAL EXCEPTION: Error: No XHR implementation has been provided. Can't read the url "app/dynamic/detail.view.html"
ORIGINAL STACKTRACE:
Error: No XHR implementation has been provided. Can't read the url "app/dynamic/detail.view.html"

看起来在动态编译期间,Angular失去了它的Xhr实现,所以它无法通过http加载html-template . 任何人都可以帮忙吗?

你可以在plunker上找到我的例子 . 版本3 - 使用templateUrl的示例(内容未动态加载)版本2 - 使用内联模板的示例(everythink工作正常) .

2 回答

  • 0

    在Angular问题中提出了类似的"bug":https://github.com/angular/angular/issues/11015

    如果您关注我的代码段,则可以使用templateUrl,但仅限于“容器”,而不是“小部件”:

    import {
      Component,
      ComponentFactoryResolver,
      ViewContainerRef,
      ViewChild,
      OnInit,
      Compiler
    } from '@angular/core';
    import {RuntimeCompiler} from "@angular/compiler";
    import {EmptyModule} from "./empty.module";
    
    export class MyComponentLoader {
      loadComponentConfig(url) {
        return fetch(url)
          .then(res => res.json())
          .then(componentList => Promise.all(
            componentList.map(config => this.loadComponent(config))
            )
          );
      }
    
      loadComponent(configObject) {
        return System.import(configObject.path)
                     .then(componentModule =>
                       componentModule[configObject.component]
                     )
      }
    }
    
    @Component({
      moduleId: module.id,
      selector: 'ng-smartdesk',
      templateUrl: './smartdesk.component.html',
      providers: [MyComponentLoader],
    })
    export class SmartdeskComponent implements OnInit {
      @ViewChild('widgets', {read: ViewContainerRef})
      container: ViewContainerRef;
    
      constructor(private _loader: MyComponentLoader,
                  protected _compiler: RuntimeCompiler) {
      }
    
      ngOnInit() {
        this._loader.loadComponentConfig('/app/config.json')
            .then(components => {
              if (components) {
                Promise.all(components.map(test => this.loadComp(test, null)));
              }
            }, error => console.log(error));
      }
    
      private loadComp(comp: Component, index: number) {
        this._compiler
            .compileComponentAsync(comp, EmptyModule)
            .then(factory => {
              this.container.createComponent(factory, index, this.container.injector)
            });
      }
    }
    

    编辑:已解决!在Tobias Bosch的帮助下,解决方案是创建一个新的编译器实例 . 这是我的最终代码:

    import {
      Component,
      ComponentFactoryResolver,
      ViewContainerRef,
      ViewChild,
      OnInit,
      Compiler, CompilerFactory
    } from '@angular/core';
    import {RuntimeCompiler} from "@angular/compiler";
    import {EmptyModule} from "./empty.module";
    import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
    
    export class MyComponentLoader {
      loadComponentConfig(url) {
        return fetch(url)
          .then(res => res.json())
          .then(componentList => Promise.all(
            componentList.map(config => this.loadComponent(config))
            )
          );
      }
    
      loadComponent(configObject) {
        return System.import(configObject.path)
                     .then(componentModule =>
                       componentModule[configObject.component]
                     )
      }
    }
    
    @Component({
      moduleId: module.id,
      selector: 'ng-smartdesk',
      templateUrl: './smartdesk.component.html',
      providers: [MyComponentLoader],
    })
    export class SmartdeskComponent implements OnInit {
      @ViewChild('widgets', {read: ViewContainerRef})
      container: ViewContainerRef;
      private _compiler;
    
      constructor(private _loader: MyComponentLoader) {
        const compilerFactory : CompilerFactory = platformBrowserDynamic().injector.get(CompilerFactory);
        this._compiler = compilerFactory.createCompiler([]);
      }
    
      ngOnInit() {
        this._loader.loadComponentConfig('/app/config.json')
            .then(components => {
              if (components) {
                Promise.all(components.map(test => this.loadComp(test, null)));
              }
            }, error => console.log(error));
      }
    
      private loadComp(comp: Component, index: number) {
        this._compiler
            .compileComponentAsync(comp, EmptyModule)
            .then(factory => {
              this.container.createComponent(factory, index, this.container.injector)
            });
      }
    }
    
  • 0

    在@Component装饰器中添加moduleId:module.id .

    有关详细信息,请查看article .

相关问题