2017-07-28 160 views
4

我一直在試圖爲此找到一個解決方案。帶動態模板或模板的角度2/4組件UIr

我有一個項目有不同的'皮膚',它們基本上是不同的模板/ Css集合。

我想讓我的組件使用基於變量THEME_DIR的皮膚。

不幸的是,我找不到如何做到這一點。我看着angular.io上的Dynamic Component Loader沒有成功。

我也看了一些答案,沒有成功。

有沒有人有想法?

這是我試過到目前爲止:

import { ComponentFactoryResolver, ViewContainerRef } from '@angular/core'; 

// @Component({ 
//  templateUrl: '../../assets/theme/'+THEME_DIR+'/login.template.html', 
// }) 

export class LoginComponent implements, AfterViewInit { 


    private log = Log.create('LoginPage'); 

    constructor(private mzksLsRequestService: MzkLsRequestService, 
       private componentFactoryResolver: ComponentFactoryResolver, 
       public viewContainerRef: ViewContainerRef) { 
    } 



    ngAfterViewInit() { 
     let componentFactory = this.componentFactoryResolver.resolveComponentFactory(new Component({ 
      templateUrl: '../../assets/theme/default/login.template.html', 
     })); 
     let viewContainerRef = this.viewContainerRef; 
     viewContainerRef.clear(); 
     let componentRef = viewContainerRef.createComponent(componentFactory); 

    } 

} 

回答

2

你可以這樣說:

import { 
    Compiler, Component, Injector, VERSION, ViewChild, NgModule, NgModuleRef, 
    ViewContainerRef 
} from '@angular/core'; 


@Component({ 
    selector: 'my-app', 
    template: ` 
     <h1>Hello {{name}}</h1> 
     <ng-container #vc></ng-container> 
    ` 
}) 
export class AppComponent { 
    @ViewChild('vc', {read: ViewContainerRef}) vc; 
    name = `Angular! v${VERSION.full}`; 

    constructor(private _compiler: Compiler, 
       private _injector: Injector, 
       private _m: NgModuleRef<any>) { 
    } 

    ngAfterViewInit() { 
    const tmpCmp = Component({ 
     moduleId: module.id, templateUrl: './e.component.html'})(class { 
    }); 
    const tmpModule = NgModule({declarations: [tmpCmp]})(class { 
    }); 

    this._compiler.compileModuleAndAllComponentsAsync(tmpModule) 
     .then((factories) => { 
     const f = factories.componentFactories[0]; 
     const cmpRef = f.create(this._injector, [], null, this._m); 
     cmpRef.instance.name = 'dynamic'; 
     this.vc.insert(cmpRef.hostView); 
     }) 
    } 
} 

只要確保該網址是正確的模板被加載到客戶端。

閱讀Here is what you need to know about dynamic components in Angular瞭解更多詳情。

+0

非常感謝這一點。我認爲現在我的問題是編譯模板時,webpack抱怨...我需要找到一種解決方法... – millerf

+1

剛剛嘗試了新的Angular cli項目,它可以很好地使用webpack。你使用什麼構建過程? –

+0

我使用離子樣板。它抱怨,當我把一個變量在模板路徑(見我的代碼THEME_DIR),因爲它似乎沒有找到正確的路徑 – millerf

0

我提供HTML有過嘗試從服務器加載dynamicaly模板時的問題(我想作安全檢查,在服務器端的翻譯。

我改變的WebPack配置後解決了這個問題。事實上,做ng eject後,它創建了包含的.ts裝載機@ngtools/webpack和webpack.config.js:

new AotPlugin({ 
    "mainPath": "main.ts", 
    "replaceExport": false, 
    "hostReplacementPaths": { 
    "environments\\environment.ts": "environments\\environment.ts" 
    }, 
    "exclude": [], 
    "tsConfigPath": "src/main/front/tsconfig.app.json", 
    "skipCodeGeneration": true 
}) 

這最後一個,是問題的根源它涉及AOT(提前)根據。到文檔: ngtools在選項部分,它被提及編輯:

skipCodeGeneration. Optional, defaults to false. Disable code generation and do not refactor the code to bootstrap. This replaces templateUrl: "string" with template: require("string")

如果你不希望你的templateUrl被編譯AOT,我建議您刪除AotPlugin,並使用TS-裝載機代替@ ngtools /的WebPack的看到:

ts-loader

的TS規則看起來就像這樣:

{ 
    test: /\.tsx?$/, 
    loader: 'ts-loader' 
} 

現在,您可以根據需要從一個相對URL加載新的模板。例如:

@Component({ 
    selector : "custom-component", 
    templateUrl : "/my_custom_url_on_server" 
}) 
export class CustomComponent { 
} 

Issue