angular - Wie man durch Section-Elemente iteriert, um sie mit ng-content zu projizieren
Ich baue einen Stepper und benutze "Transklusion" mit ng-content, um dynamisch section-Elemente innerhalb des Stepper-Tags zu erfassen. Die Ansicht der stepper.component funktioniert so:
<ng-content select=".one"></ng-content>
<ng-content select=".two"></ng-content>
<ng-content select=".three"></ng-content>
Die Verwendung von Komponenten sieht so aus:
<stepper>
<section class="one">content here<section>
<section class="two">content here<section>
<section class="three">content here<section>
</stepper>
Ich möchte es jedoch dynamisch gestalten, indem ich die Abschnittelemente automatisch erkenne:
<ng-content *ngFor="let section of sections; index as i;" select="['section:nth-child(' + i + ')']"></ng-content>
Wie kann ich:
- Erhalte eine NodeList der für die Transklusion verfügbaren Section-Elemente?
- Verwenden Sie das
selectvon ng-content, um sie schrittweise anzusprechen?
Antwort #1
Ich würde eine Direktive erstellen wie:
@Directive({
selector: '[stepper-section]'
})
export class StepperSectionDirective {}
füge dann jedem Abschnitt das Attribut stepper-section hinzu:
<stepper>
<section stepper-section>content here<section>
<section stepper-section>content here<section>
<section stepper-section>content here<section>
</stepper>
und schließlich den @ContentChildren-Dekorator verwenden, um alle Abschnitte abzufragen:
@ContentChildren(StepperSectionDirective) sections: QueryList<StepperSectionDirective>;
Ng-run Beispiel
Wenn Sie den Inhalt durchlaufen und dynamisch rendern möchten, können Sie Ihre Kinder mit ng-template umschließen und die Direktive ngTemplateOutlet verwenden, um sie in StepperComponent zu rendern:
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-section.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 Beispiel
Der Unterschied zwischen diesen beiden Ansätzen besteht darin, dass im ersten Fall sämtlicher untergeordneter Inhalt gerendert wird und wir lediglich das display: none auf die Schritte anwenden, die wir verbergen möchten.
Im zweiten Ansatz haben wir mehr Kontrolle darüber, was wir rendern wollen, und wir rendern jeweils nur einen Schritt zu einer bestimmten Zeit.
