2017-05-30 47 views
1

採用了棱角分明4.1,我試圖動態地改變模塊類型的模板模塊渲染之前。這可能嗎?動態改變模板的角4個組件

我們自舉在頁面上的未知數量的部件(從組件類型的已知列表),並且頁面可以包含相同類型的多個組件。我已經找到了一種方法來爲每個這些組件提供一個不同的選擇器,以便它們可以分別呈現(即使它們屬於同一類型),但我還需要爲每個選擇一個不同的模板。 模板應該是所選元素的內部HTML。

下面的代碼:

import { Component, NgModule, Inject, ApplicationRef, ComponentFactoryResolver, OpaqueToken, Type } from '@angular/core'; 
import { BrowserModule } from '@angular/platform-browser'; 
import { MyNavComponent } from './MyNav.component'; 
import { MyRotatorComponent } from './MyRotator.component'; 
import { MySignUpComponent } from './MySignUp.component'; 

export const BOOTSTRAP_COMPONENTS_TOKEN = new OpaqueToken('bootstrap_components'); 

@NgModule({ 
    imports: [BrowserModule], 
    declarations: [ 
     MyNavComponent, 
     MyRotatorComponent, 
     MySignUpComponent 
    ], 
    entryComponents: [ 
     MyNavComponent, 
     MyRotatorComponent, 
     MySignUpComponent 
    ], 
    providers: [ 
     { 
      provide: BOOTSTRAP_COMPONENTS_TOKEN, 
      useValue: [ 
       { type: MyNavComponent }, 
       { type: MyRotatorComponent }, 
       { type: MySignUpComponent } 
      ] 
     }, 
    ] 
}) 
export class AppModule { 
    constructor(
     private resolver: ComponentFactoryResolver, 
     @Inject(BOOTSTRAP_COMPONENTS_TOKEN) private components: [Component], 
    ) { } 
    ngDoBootstrap(appRef: ApplicationRef) { 
     console.log(this.components); 
     this.components.forEach((componentDef: { type: Type<any>, selector: string }) => { 
      const factory = this.resolver.resolveComponentFactory(componentDef.type); 
      let selector = factory.selector; 
      let nodes = document.querySelectorAll(selector); 
      for (let i = 0; i < nodes.length; i++) { 
       let node = nodes[i]; 
       (<any>factory).factory.selector = node; 

       //The next line doesn't work... how can I dynamically set the template? 
       (<any>factory).factory.template = node.innerHTML; 

       appRef.bootstrap(factory); 
      } 
     }); 
    } 
} 

由於靠近上述代碼的最後指出,(<any>factory).factory.template = node.innerHTML;不起作用。我也嘗試修改類型的元數據,但這也不起作用。

是什麼,我想通過另一種方式來實現可能嗎?如果沒有,這是否值得作爲功能請求提交?

(注:上面的代碼在https://github.com/angular/angular/issues/7136是基於對他人的代碼的一部分。)

更新:

我想知道如果在角的未來更新我就可以通過將模板設置爲<ng-content></ng-content>以包含所選元素的innerHTML來實現相同的結果。這對於自舉組件是不可能的,但基於這個issue on Git,我希望它很快就會有。

+0

您使用的是AOT嗎?更確切地說,你是否要將@角/編譯器發佈到生產環境中? – yurzui

+0

@yurzui我剛剛得到了一個新的Angular,並且還沒有設置AOT編譯,但我認爲使用AOT最終會是理想的。這會改變什麼嗎?如果我堅持使用JIT,我能否把它解決? –

+0

我可能並不理解你的問題的所有細節,但我認爲你可以通過使用'* ngFor'和'* ngSwitch'結構指令來實現你想要的。 與'ngFor',你循環你需要的組件總數。 與'ngSwitch',你可以根據某些變量自由選擇已知的一組組件。 –

回答

0

被創建後,您不能設置一個組件工廠的模板。 Angular編譯器在生成工廠時解析模板併爲每個組件創建一個視圖類。在創建組件工廠及其視圖類後,您無法對其進行修改。在您的例子中,你正在使用ComponentFactoryResolver

const factory = this.resolver.resolveComponentFactory(componentDef.type); 

返回已創建的工廠。

唯一的選擇是編譯器生成的工廠之前更改模板。但我不認爲這是可能的。您可能需要查看組件的動態生成。

閱讀Here is what you need to know about dynamic components in Angular以獲取更多信息。

+0

感謝您的解釋和有用的文章,@Maximus。你說的話很有道理。我將繼續希望有一段時間,在將解決方案標記爲答案並關閉具有動態模板的引導組件的想法之前,還有另一種實現方法。 –

+1

當然,沒問題。無論如何,模板必須由編譯器編譯。如果你有一個編譯模板,那麼你可以將它用於不同的目的。您可以使用'ng-template'指令來獲得已編譯的模板。但我不確定此解決方案是否適用於您的情況。 –