web-dev-qa-db-fra.com

Angular 2/4 composant avec template dynamique ou templateUrl

J'ai essayé de trouver une solution pour cela partout.

J'ai un projet avec différents "skins", qui sont fondamentalement différents ensembles de modèles/Css.

J'essaie de faire en sorte que mes composants utilisent la peau en fonction d'une variable THEME_DIR.

Malheureusement, je ne trouve pas comment faire pour que cela se produise. J'ai regardé dans le composant dynamique Loader sur angular.io sans succès.

J'ai aussi 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);

    }

}
6
millerf

Vous pouvez le faire comme ça:

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 simplement que l'URL est correcte et que le modèle est chargé dans le client.

Lire Voici ce que vous devez savoir sur les composants dynamiques dans Angular pour plus de détails.

10

J'ai eu le problème en essayant de charger des templates dynamiques sur le serveur (je voulais vérifier la sécurité, la traduction côté serveur avant de servir le langage HTML.

Je l'ai résolu après avoir changé la configuration de webpack. En fait, après avoir utilisé ng eject, il a créé un fichier 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. Cela concerne l'AOT (Ahead Of Time). Selon la documentation: Ngtools dans la section options, il est mentionné:

skipCodeGeneration. Facultatif, la valeur par défaut est false. Désactiver le code génération et ne pas refactoriser le code pour bootstrap. Ceci remplace templateUrl: "chaîne" par modèle: require ("chaîne")

Si vous ne voulez pas que votre templateUrl soit compilé AOT, je vous recommande de supprimer AotPlugin, et d'utiliser ts-loader au lieu de @ ngtools/webpack, voir:

ts-loader

La règle pour ts ressemblera à ceci:

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

Vous pouvez désormais charger de nouveaux modèles à partir d'une URL relative à la demande. Exemple :

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

Voir Numéro

1
Yacine