angular - Hur man loopar igenom sektionselement för att projicera med ng-innehåll


Jag bygger en stegmotor och använder "transklusion" med ng-content för att dynamiskt hämta section-element inom stegmotor-taggen. Stegmotor.component-vyn fungerar så här:

<ng-content select=".one"></ng-content>
<ng-content select=".two"></ng-content>
<ng-content select=".three"></ng-content>

Komponentanvändning ser ut så här:

<stepper>
    <section class="one">content here<section>
    <section class="two">content here<section>
    <section class="three">content here<section>
</stepper>

Jag skulle dock vilja göra det dynamiskt genom att automatiskt känna igen sektionsdelarna:

<ng-content *ngFor="let section of sections; index as i;" select="['section:nth-child(' + i + ')']"></ng-content>

Hur kan jag:

  1. få en nodeList av de sektionselement som finns tillgängliga för transkludering?
  2. använd ng-content's select för att rikta dem stegvis?

Svar #1

Jag skulle skapa en direktiv som:

@Directive({
  selector: '[stepper-section]'
})
export class StepperSectionDirective {}

lägg sedan till stepper-section-attributet till varje avsnitt:

<stepper>
    <section stepper-section>content here<section>
    <section stepper-section>content here<section>
    <section stepper-section>content here<section>
</stepper>

och slutligen använda @ContentChildren-dekoreraren för att fråga alla sektioner:

@ContentChildren(StepperSectionDirective) sections: QueryList<StepperSectionDirective>;

Ng-run Exempel

Om du vill loopa igenom innehåll och rendera det dynamiskt kan du omsluta dina barn med ng-template och använda ngTemplateOutlet-direktivet för att rendera dem i StepperComponent:

html

<app-stepper>
  <ng-template stepper-section>Content 1</ng-template>
  <ng-template stepper-section>Content 2</ng-template>
  <ng-template stepper-section>Content 3</ng-template>
</app-stepper>

stepper-sektion.directive.ts

@Directive({
  selector: '[stepper-section]'
})
export class StepperSectionDirective {
  hidden = false;

  constructor(public templateRef: TemplateRef<any>) {}
}

stepper.component.ts

@ContentChildren(StepperSectionDirective) sectionDirs: QueryList<StepperSectionDirective>;

stepper.component.html

<button *ngFor="let section of sections; index as i;"
       [class.enabled]="activeSection === i" (click)="goTo(i)">
  Step {{ i + 1 }}
</button>
<div class="content">
  <ng-container *ngFor="let section of sections">
    <ng-template *ngIf="!section.hidden" 
         [ngTemplateOutlet]="section.templateRef"></ng-template>
  </ng-container>
</div>

Ng-run Exempel

Skillnaden mellan dessa två tillvägagångssätt är att i det första fallet renderas allt barninnehåll och vi manipulerar endast display: none för de steg vi vill dölja.

I den andra metoden har vi mer kontroll över vad vi vill rendera och vi renderar bara ett steg vid en specifik tidpunkt.

Relaterade artiklar