I would create a directive like:
@Directive({
selector: '[stepper-section]'
})
export class StepperSectionDirective {}
then add stepper-section
attribute to each of sections:
<stepper>
<section stepper-section>content here<section>
<section stepper-section>content here<section>
<section stepper-section>content here<section>
</stepper>
and finally make use of @ContentChildren
decorator to query all the sections:
@ContentChildren(StepperSectionDirective) sections: QueryList<StepperSectionDirective>;
Ng-run Example
If you want to loop through content and render it dynamically you can wrap your children with ng-template
and use ngTemplateOutlet
directive to render them in 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-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 Example
The difference between these two approaches is that in the first case all child content gets rendered and we only manipulate display: none
to those steps we want to hide.
In the second approach we have more control on what we want to render and we render only one step at specific time.