首页 > 解决方案 > Angular Material Stepper 可重复使用的表单,具有单独的步骤作为组件

问题描述

我正在使用 Angular Material 步进器,它在 1 个组件中作为整个代码运行良好。但是步进器将用于大约 10 个不同的组件。有 7 种不同类型的表单,如输入、选择、名称、表格等。所以我想我会将 stepper 分成单独的组件,其中每个组件都是一个步骤。所以,我决定为表格制作一个模板app-step-form

<form [formGroup]="myForm">
  <mat-vertical-stepper [linear]="isLinear" #stepper>
      <ng-content></ng-content>
  </mat-vertical-stepper>
</form>

而不是像这样创建不同的步骤app-table-select

  <mat-step [stepControl]="tableControl">
    <ng-template matStepLabel>Table </ng-template>
    <mat-form-field appearance="fill">
      <mat-label>Choose table</mat-label>
      <mat-select [formControl]="tableControl">
        <mat-option *ngFor="let table of tables" [value]="table.value">
          {{table.viewValue}}
        </mat-option>
      </mat-select>
    </mat-form-field>
    <div>
      <button mat-button matStepperNext>Next</button>
    </div>
  </mat-step>

而不是像这样的步骤插入组件

<app-step-from>

  <app-table-select>
  </app-table-select>

  <app-name-input>
  </app-name-input>

</app-step-from>

所以我会有表单模板在不同的组件中使用,而不是每次都一个一个地创建。

但我面临的问题是,如果我使用上面显示的步骤组件,它在app-step-form. 对此进行小改动app-step-form并提取<mat-step></mat-step>

<form [formGroup]="myForm">
  <mat-vertical-stepper [linear]="isLinear" #stepper>
    <mat-step>
      <ng-content></ng-content>
    </mat-step>
  </mat-vertical-stepper>
</form>

然后像这样取出mat-step并放入<ng-template>

<ng-template>
    <ng-template matStepLabel>Table </ng-template>
    <mat-form-field appearance="fill">
      <mat-label>Choose table</mat-label>
      <mat-select>
        <mat-option *ngFor="let table of tables" [value]="table.value">
          {{table.viewValue}}
        </mat-option>
      </mat-select>
    </mat-form-field>
</ng-template>

使此步骤可见,app-step-form但不能从中传递步骤组件标签, <ng-template matStepLabel>Table </ng-template>并且此标签不可见或@Input()两者都不使用。

我花了 2 天的时间试图解决这个问题,寻找答案,但到目前为止还没有那么天真,也失去了如何克服这个问题以使我的步进器可重复使用的想法。

有谁知道如何使这个想法发挥作用?还是不可能按照我想象的方式进行?

还有任何想法如何使这些输入像 1 形式的一部分?子表单合并到 1 个表单还是什么?

标签: angularangular-materialangular-material-stepper

解决方案


它可能关注的对象 - 我没有找到任何解决此问题的方法。

我尝试创建 1 个可重用组件,其中包含每个可能的输入,并根据其所在的路径通过 * ngIf指令显示其中的每个输入,例如:

<app-step-form [path]='/your-path'></app-step-from>并且每条路径都有每个可能的输入,但事实证明它有很多意想不到的漏洞。许多不需要的字段不必要地插入到数据库中(您可以并且应该避免的地方),所以......

我决定通过以下方式使用每个独立组件分别创建每个表单:

    this.parentForm = this.fb.group({
      records: new FormControl(null,
        [
          Validators.required,
          Validators.min(2),
          Validators.max(255),
          Validators.pattern('^(0|[1-9][0-9]*)$')
        ],
        ),
      value: new FormControl(null),
    });

作为组件的每个输入都在其中提供了验证器,因此无需担心每个表单中的验证 pf 字段。例子:

<form [formGroup]="parentForm">
  <mat-vertical-stepper [linear]="isLinear" #stepper>
    <mat-step [stepControl]="parentForm">
      <ng-template matStepLabel>Records</ng-template>
      <app-material-input [parentForm]="parentForm"></app-material-input>
      <div>
        <app-mat-stepper-next-button></app-mat-stepper-next-button>
      </div>
    </mat-step>
    <mat-step [stepControl]="parentForm">
      <ng-template matStepLabel>Value</ng-template>
      <app-material-input [parentForm]="parentForm"></app-material-input>
      <div>
        <app-mat-stepper-next-button></app-mat-stepper-next-button>
      </div>
    </mat-step>
    <mat-step>
      <ng-template matStepLabel>We're done!</ng-template>
      <app-mat-stepper-back-button></app-mat-stepper-back-button>
      <button mat-flat-button (click)="onSubmit(parentForm)">Submit</button>
    </mat-step>
  </mat-vertical-stepper>
</form>

父组件中的 parentForm: parentForm: FormGroup

在子组件中: @Input() parentForm: FormGroup;

就是这样。它可以通过 1 个表单显示输入来完成,具体取决于参数或路径,但通过创建单独的表单FormBuilder而不是为每个需要它的地方使用 1 个表单更有意义。


推荐阅读