2017-07-28 7 views
4

Ich habe versucht, eine Lösung für diese überall zu finden.Angular 2/4 Komponente mit dynamischen Vorlage oder TemplateUrl

Ich habe ein Projekt mit verschiedenen "Skins", die grundsätzlich verschiedene Sätze von Vorlagen/Css sind.

Ich versuche, meine Komponenten verwenden die Haut basierend auf einer Variablen THEME_DIR.

Leider kann ich nicht finden, wie man das macht. Ich schaute in die Dynamic Component Loader auf angular.io ohne Erfolg.

Ich sah auch hier ein paar Antworten ohne Erfolg.

Hat jemand eine Idee?

Das ist, was ich bisher versucht:

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

    } 

} 

Antwort

2

Sie es wie folgt tun:

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

nur sicherstellen, dass die URL korrekt ist und die Vorlage wird in den Client geladen.

Lesen Sie Here is what you need to know about dynamic components in Angular für weitere Details.

+0

Vielen Dank dafür. Ich denke, jetzt ist mein Problem Webpack beschweren sich beim Zusammenstellen der Vorlagen ... Ich muss einen Weg finden, um ... – millerf

+1

Nur auf dem frischen neuen Angular cli-Projekt versucht, funktioniert es gut mit Webpack. Welchen Build-Prozess verwenden Sie? –

+0

Ich verwende eine ionische Boilerplate. Es beschwert sich, wenn ich eine Variable in den Vorlagenpfad einfüge (siehe THEME_DIR in meinem Code), da es scheint, dass es den richtigen Pfad nicht findet – millerf

0

Ich hatte das Problem, wenn dynamicaly Vorlagen vom Server zu laden versuchen, (i vor dem Servieren html Sicherheitsüberprüfung, Übersetzung auf Server-Seite machen wollte.

ich es nach dem Wechsel webpack Config gelöst habe. In der Tat, nach ng eject tun, schuf er eine webpack.config.js, die eine .ts loader @ngtools/webpack und enthält:.

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

das letzte, ist der Ursprung des Problems es die AOT betrifft (im voraus) Laut. zur Dokumentation: ngtools im Optionsbereich, es wird erwähnt 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")

Wenn Sie nicht wollen, Ihre templateUrl zusammengestellt AOT sein, ich empfehlen Ihnen die AotPlugin, zu entfernen und statt des ts-Loader verwenden von @ ngtools/webpack sehen:

ts-loader

Die Regel für ts wird wie folgt aussehen:

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

Jetzt können Sie frische Vorlagen aus einer relativen URL auf Anfrage laden. Beispiel:

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

Siehe Issue

Verwandte Themen