Vyhledávání na webu

html - Angular 4 - Jak zobrazit šablonu komponenty děděné třídy


Snažím se zobrazit seznam položek (komponent) podle jejich typů:

Mám pole komponent. Všechny dědí z základní třídy. Typ pole je definován jako typ základní třídy. Chci pole zobrazit (řekněme jako seznam položek), přičemž každá položka má svou vlastní šablonu, místo základní šablony.

Zkoušel jsem to:

V souboru app.component.html:

<app-shape *ngFor="let shape of shapes"></app-shape>

V souboru app.component.ts:

shapes: ShapeComponent[] = [new CircleComponent(), new SquareComponent()];

Definoval jsem 3 komponenty:

export class ShapeComponent {
}

export class CircleComponent extends ShapeComponent{
}

export class SquareComponent extends ShapeComponent{
}

A výsledkem je, že dostanu seznam tvarů.

Podporuje Angular takovou věc?

Díky!

Odpověď č. 1

Deklarativní přístup

Můžete použít ngComponentOutlet.

Kód :

shapes: ShapeComponent[] = [CircleComponent, SquareComponent];

šablona :

<ng-container *ngFor="let shape of shapes">
    <ng-container *ngComponentOutlet="shape">
    </ng-container>
</ng-container>

ngComponentOutlet - Instanciuje jeden typ komponenty a vkládá její hostitelský pohled do aktuálního pohledu. NgComponentOutlet poskytuje deklarativní přístup pro dynamické vytváření komponent.

NgComponentOutlet vyžaduje typ komponenty, pokud je nastavena nepravdivá hodnota, zobrazení se vymaže a jakákoli existující komponenta bude zničena.

Takže v šabloně není potřeba žádný tvrdý kód. *ngFor bude iterovat přes pole typů komponent ve vašem kódu

Aktualizace

Nezapomeňte přidat komponentu dynamického vykreslování do entryComponents AppModule:

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent, HelloComponent, AComponent, BComponent ],
  entryComponents: [
    AComponent, BComponent 
  ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

Ukázka StackBlitz

Imperativní přístup s nastavováním dat

app-component.template:

<ng-container #comps>

</ng-container>

Získejte přístup k zobrazení #comps(ng-container) pomocí dekorátoru ViewChild a vytvořte komponenty. Takže nemůžete inicializovat komponentu jako b=new BComponent().

  1. Nejdříve je potřeba vyřešit továrnu komponent.
  2. Inicializujte komponentu pomocí metody createComponent objektu viewContainerRef. Vrací odkaz na instanci komponenty.
  3. Pomocí reference získejte přístup k vlastnosti instance a aktualizujte libovolná data podle potřeby

app-component.ts:

 @ViewChild('comps', { read: ViewContainerRef }) comps: ViewContainerRef;
  constructor(private componentFactoryResolver: ComponentFactoryResolver) {

  }

ngOnInit() {
    this.comps.clear();
    let aComponentFactory = this.componentFactoryResolver.resolveComponentFactory(this.compArr[0]);
    let aComponentRef = this.comps.createComponent(aComponentFactory);
    (<AComponent>aComponentRef.instance).name = 'A name';

    let bComponentFactory = this.componentFactoryResolver.resolveComponentFactory(this.compArr[1]);

    let bComponentRef = this.comps.createComponent(bComponentFactory);
    (<BComponent>bComponentRef.instance).name = 'B name';
  }

Demo StackBlitz

Odpověď č. 2

Každá součást musí mít samostatný selektor.

import {Component} from "@angular/core";

@Component({
  selector: "app-shape" //maybe even is not needed here
})
class Shape {

}

@Component({
  selector: "app-rect"
})
class Rect extends Shape {

}

Takže můžete udělat něco takového.

<div *ngFor="let shape of shapes">
  <app-rect *ngIf="//check if shape is rect"></app-rect>
  <app-circle *ngIf="//check if shape is circle"></app-circle>
</div>