angular - Rendera komponent dynamiskt


Jag har denna array:

this.dashboard = [
     {name: '<app-incassi-provvigioni></app-incassi-provvigioni>'},
     {name: '<app-scheda-punti-vendita></app-scheda-punti-vendita>'}
]

Jag fyller denna array på ngOnInit-cykeln. Jag undrade hur jag kan rendera komponenterna när jag läser min array i HTML på det sättet:

<gridster [options]="gridsterOptions">
    <gridster-item [item]="item" *ngFor="let item of dashboard">
        <!-- your content here -->
        {{item.name}}
    </gridster-item>
</gridster>

Självklart returnerar det just nu strängen som finns i objektet, men jag försöker hitta en lösning för att rendera komponenten. Är det möjligt att göra det?

Mer detaljer: Jag utvecklar en dashboard-typ av app där jag hämtar listan över användarens dashlet från databasen och jag försöker rendera dessa komponenter dynamiskt när huvudapp-komponenten är klar. Använder Angular 7 och Gridster2.

Svar #1

Du kan injicera komponent dynamiskt

Skapa bara komponent med @Input() komponent;

export class DynamicContentComponent implements OnInit {

  @Input() component: any;
  @Input() data: any;

  constructor(public viewContainerRef: ViewContainerRef,
              private componentFactoryResolver: ComponentFactoryResolver) { }

  ngOnInit() {
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.component);
    this.viewContainerRef.clear();

    const componentRef = this.viewContainerRef.createComponent(componentFactory);
    (<DynamicComponentRef>componentRef.instance).data = this.data;
  }
}

Och använd det i HTML

<app-dynamic-content [component]="someComponent" [data]="data"></app-dynamic-content>

Dataexempel

someComponent = SchedaPuntiVendita;

Dynamiska komponenter bör läggas till i entryComponents i din module

Du kan också skapa någon slags fabrik som tar emot en sträng och beroende på den returnerar dig komponentklassen

Fabrikexempel

@Injectable()
export class DynamicContentComponentFactory {

  constructor() { }

  get(type: ContentType): any {
    switch (type) {
      case 'scheda':
        return SchedaPuntiVendita;
    }
  }

Och ändra DynamicContentComponent lite

@Input() contentType: string;

constructor(..., private factory: DynamicContentComponentFactory) { }
...

const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.factory.get(this.contentType));

...

Svar #2

Istället för att skicka komponenttaggens namn ("app-incassi-provvigioni" i ditt fall), skicka komponentnamnet (TestComponenet), sedan kalla på funktionen från din vy och rendera den dynamiskt med Directive.

t.ex :

<gridster [options]="gridsterOptions">
  <gridster-item [item]="item" *ngFor="let item of dashboard">
    <div class="inner">
      <ng-template dynamic-template> </ng-template>
    </div>
  </gridster-item>
</gridster>

dynamic-template är en direktiv som hjälper oss att ladda komponenten.

Relaterade artiklar