web-dev-qa-db-fra.com

Modèle dynamique dans le composant Angular 6

Je suis nouveau sur Angular, donc je suis désolé si je bousille le jargon. J'essaie d'utiliser dynamiquement templateURL (html) dans mon composant, la fonction Class restera la même mais html changera en fonction de binType

Ceci est ma source de classe de composant

import { Component, OnInit, Input, Output, EventEmitter, AfterViewInit, ViewContainerRef, ViewChild, Compiler, Injector, NgModule, NgModuleRef } from '@angular/core';

declare var module: {
  id: string;
}

@Component({
  selector: 'app-cart-bin',
  styleUrls: ['./cart-bin.component.css'],  
  template: ` 
      <ng-template #dynamicTemplate></ng-template>
    `

})

export class CartBinComponent implements AfterViewInit, OnInit {

  @ViewChild('dynamicTemplate', {read: ViewContainerRef}) dynamicTemplate;


  public cols = 3;
  public rows = 3;

  @Input() binType = "";

  @Input() toteList = [];

  @Output() callbackMethod = new EventEmitter<string>();

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

  ngOnInit() {
    console.log(this.binType);
  }

  ngAfterViewInit() {

    let tmpObj;

    console.log(tmpObj);

    if ((this.binType) == "2") {
      tmpObj = {
        moduleId: module.id,
        templateUrl : './cart-bin.component_02.html'
      };
    } else {
      tmpObj = {
        moduleId: module.id,
        templateUrl : './cart-bin.component_01.html'
      };
    }

    console.log(tmpObj);

    const tmpCmp = Component(tmpObj)(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.dynamicTemplate.insert(cmpRef.hostView);
    });
}

  getToteBoxClass(toteData){
    ...
  } 

  getToteIcon(toteData){
    ...
  }

  toteSaveClick(toteData){
    ...
  }
}

Ceci est en cours de compilation mais le modèle n'est pas en train d'analyser et d'obtenir l'erreur suivante

ERROR Error: Template parse errors:
Can't bind to 'ngStyle' since it isn't a known property of 'div'.

Le HTML est correct, je l'ai utilisé directement dans le cadre de @Component TypeDecorator

4
MediocreDev

Outre le fait que l'utilisation du compilateur et la création de composants dynamiques sont assez anti-pattern en angulaire, je pense que vous pouvez corriger votre erreur en ajoutant le CommonModule à votre déclaration NgModule:

NgModule({imports: [CommonModule], declarations: [tmpCmp]})

Il serait préférable d'utiliser un ngSwitchCase dans votre modèle, de créer deux composants qui héritent d'un composant de base mais ont des modèles différents, et en fonction du binType laissez-le rendre l'un ou l'autre composant:

modèle:

<ng-container [ngSwitch]="binType">
  <cart-bin-1 *ngSwitchCase="1"></cart-bin-1>
  <cart-bin-2 *ngSwitchCase="2"></cart-bin-2>
</ng-container>

ts:

export abstract class CartBin {
  // some common cart bin logic here:
}


@Component({
  selector: 'cart-bin-1',
  templateUrl: './cart-bin.component_01.html' 
})
export class CartBin1 extends CartBin {

}

@Component({
  selector: 'cart-bin-2',
  templateUrl: './cart-bin.component_02.html' 
})
export class CartBin2 extends CartBin  {

}

L'avantage de l'utiliser, c'est que le bundle AOT n'inclura plus le compilateur, et donc de rendre votre application plus petite et plus rapide. En outre, cela semble beaucoup mieux :)

4
PierreDuc