2016-08-18 83 views
1

我想让Angular 2使用RuntimeCompiler动态编译HTML的一个片段。我在post找到了解决方案(请参阅Angular 2.0 RC 5相关的答案),直到我在组件的装饰器中使用templateUrl而不是内联模板为止。Angular 2 RuntimeCompiler:没有提供XHR实现

@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" 

它看起来像动态编译期间角失去它的XHR实现,因此无法通过HTTP加载HTML模板。 任何人都可以帮忙吗?

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

回答

0

类似的“错误”中的角问题被提出: 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

+0

谢谢你,@sbeci。不幸的是你的解决方案不起作用 - 如果这是module.id的问题,我只会得到404错误 - 但我的错误更棘手 –

相关问题