2017-07-28 1 views
4

J'ai essayé de trouver une solution pour cela partout.Composant angulaire 2/4 avec gabarit dynamique ou templateUrl

J'ai un projet avec différents «skins», qui sont fondamentalement différents ensembles de templates/Css. J'essaye d'avoir mes composants utilisent l'habillage basé sur une variable THEME_DIR.

Malheureusement, je n'arrive pas à trouver comment cela se passe. J'ai regardé dans le Dynamic Component Loader sur angular.io sans succès.

J'ai également regardé quelques réponses ici sans succès non plus.

Est-ce que quelqu'un a une idée?

C'est ce que j'ai essayé jusqu'à présent:

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); 

    } 

} 

Répondre

2

Vous pouvez le faire comme ceci:

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); 
     }) 
    } 
} 

Assurez-vous que l'URL est correcte et le modèle est chargé dans le client. Pour plus de détails, veuillez consulter Here is what you need to know about dynamic components in Angular.

+0

Merci beaucoup pour cela. Je pense maintenant que mon problème est de se plaindre de webpack lors de la compilation des templates ... J'ai besoin de trouver un moyen de contourner ça ... – millerf

+1

Juste essayé sur le nouveau projet Angular cli, ça marche bien avec webpack. Quel processus de construction utilisez-vous? –

+0

J'utilise un passe-partout ionique. Il se plaint quand je mets une variable dans le chemin du template (voir THEME_DIR dans mon code) car il semble qu'il ne trouve pas le bon chemin – millerf

0

J'ai eu le problème en essayant de charger dynamiquement des modèles à partir du serveur (je voulais faire vérifier la sécurité, la traduction sur le côté serveur avant de servir html.

Je l'ai résolu après avoir changé config webpack. En fait, après avoir fait ng eject, il a créé un webpack.config.js qui contient un chargeur .ts @ngtools/webpack et:.

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

Ce dernier, est l'origine du problème, il concerne l'AOT (Ahead Of Time) d'après. à la documentation: ngtools dans la section options, c'est mentionné ed:

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

Si vous ne voulez pas votre templateURL à compiler AOT, je vous recommandons de supprimer le AotPlugin et à l'utilisation des ts-chargeur au lieu de @ ngtools/webpack voir:

ts-loader

La règle ts ressemblera à ceci:

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

vous pouvez maintenant charger des modèles frais à partir d'une URL relative à la demande. Exemple:

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

Voir Issue