4

我正在构建一个步进器并使用“嵌入”ng-content来动态抓取section步进器标签中的元素。stepper.component 视图的工作方式如下:

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

组件用法如下所示:

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

但是,我想通过自动识别部分元素来使其动态化:

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

我怎样才能:

  1. 获取可用于嵌入的部分元素的节点列表?
  2. 使用 ng-contentselect来逐步定位它们?
4

1 回答 1

5

我会创建一个指令,如:

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

然后stepper-section为每个部分添加属性:

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

最后使用@ContentChildren装饰器查询所有部分:

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

Ng 运行示例

如果你想遍历内容并动态渲染它,你可以用StepperComponent包装你的孩子ng-template并使用指令来渲染它们:ngTemplateOutlet

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 运行示例

这两种方法的区别在于,在第一种情况下,所有子内容都被渲染,我们只操作display: none我们想要隐藏的那些步骤。

在第二种方法中,我们可以更好地控制要渲染的内容,并且在特定时间只渲染一个步骤。

于 2019-12-17T19:56:16.687 回答