首页 > javascript > Angular Material Mat-Stepper:如何在多个步骤中使用相同的formgroup?

Angular Material Mat-Stepper:如何在多个步骤中使用相同的formgroup? (Angular Material Mat-Stepper: How to use the same formgroup for multiple steps?)

问题

这是我的表格组。我正在另一个中使用表单组:

this.shopGroup = this.fb.group({
  _user: [''],
  name: ['', Validators.compose([Validators.required, Validators.maxLength(60)])],
  url_name: [''],
  desc: ['', Validators.compose([Validators.required, Validators.maxLength(600)])],
  photos: [''],
  currency: ['Real'],
  language: ['Português do Brasil'],
  address: this.fb.group({
    zipcode: ['', Validators.compose([Validators.required, Validators.pattern('[0-9]{5}[\-]?[0-9]{3}')])],
    street: ['', Validators.compose([Validators.required, Validators.maxLength(70)])],
    number: [null, Validators.compose([Validators.required, Validators.max(99999)])],
    complement: ['', Validators.maxLength(30)],
    district: ['', Validators.compose([Validators.required, Validators.maxLength(60)])],
    state: ['', Validators.required],
    city: ['', Validators.compose([Validators.required, Validators.maxLength(70)])]
  }),
  status: [true],
  created_at: [new Date()],
  updated_at: [new Date()]
});

这是模板:

<form [formGroup]="shopGroup">
  <mat-horizontal-stepper [linear]="isLinear" #stepper>
    // Im not sure how to set stepControl
    <mat-step [stepControl]="?">
        <ng-template matStepLabel>Store Creation</ng-template>
        <mat-form-field>
          <input matInput placeholder="Nome" formControlName="name">
        </mat-form-field>
        ...
        <div>
          <button mat-button matStepperNext type="button">Next</button>
        </div>
    </mat-step>
    // Im not sure how to set stepControl
    <mat-step formGroupName="address" [stepControl]="?">
      <ng-template matStepLabel>Configuração do Envio/Frete</ng-template>
      <mat-form-field>
        <input matInput placeholder="CEP" formControlName="zipcode">
      </mat-form-field>
      ...
      <div>
        <button mat-button matStepperPrevious>Back</button>
        <button mat-button matStepperNext>Next</button>
      </div>
    </mat-step>
    <mat-step>
      <ng-template matStepLabel>Done</ng-template>
      You are now done.
      <div>
        <button mat-button matStepperPrevious>Back</button>
      </div>
    </mat-step>
  </mat-horizontal-stepper>
</form>

这是Angular Material单个表单的文档:

<form [formGroup]="formGroup">
  <mat-horizontal-stepper formArrayName="formArray" linear>
    <mat-step formGroupName="0" [stepControl]="formArray.get([0])">
      ...
      <div>
        <button mat-button matStepperNext type="button">Next</button>
      </div>
    </mat-step>
    <mat-step formGroupName="1" [stepControl]="formArray.get([1])">
      ...
      <div>
        <button mat-button matStepperPrevious type="button">Back</button>
        <button mat-button matStepperNext type="button">Next</button>
      </div>
    </mat-step>
    ...
  </mat-horizontal-stepper>
</form>

我想shopGroup在第一步使用,然后在第二步使用address(shopGroup内的组)。最后,我想发送shopGroup。我知道我需要type="button"在步骤之间设置type="submit",但最后,我不知道如何设置[stepControl]从一步到另一步。如何使它在模板(html)上工作?

解决方法

您可以在官方文档中阅读如何使用单一表单处理mat-stepper

首先,您需要定义一个表格组的数组:

this.formGroup = this._formBuilder.group({
      formArray: this._formBuilder.array([
        this._formBuilder.group({
          firstNameFormCtrl: ['', Validators.required],
          lastNameFormCtrl: ['', Validators.required],
        }),
        this._formBuilder.group({
          emailFormCtrl: ['', Validators.email]
        }),
      ])
    });

其次,您需要能够返回将在HTML模板上使用的formGroup数组:

  get formArray(): AbstractControl | null {
    return this.dictationForm.get('formArray');
  }

然后,您应该将每个元素mat-step与特定的组formArray元素相关联:

<mat-step formGroupName="0" [stepControl]="formArray?.get([0])"></mat-step>

你可以在这里找到一个有效的例子

问题

This is my form group. I'm using a form group inside another one:

this.shopGroup = this.fb.group({
  _user: [''],
  name: ['', Validators.compose([Validators.required, Validators.maxLength(60)])],
  url_name: [''],
  desc: ['', Validators.compose([Validators.required, Validators.maxLength(600)])],
  photos: [''],
  currency: ['Real'],
  language: ['Português do Brasil'],
  address: this.fb.group({
    zipcode: ['', Validators.compose([Validators.required, Validators.pattern('[0-9]{5}[\-]?[0-9]{3}')])],
    street: ['', Validators.compose([Validators.required, Validators.maxLength(70)])],
    number: [null, Validators.compose([Validators.required, Validators.max(99999)])],
    complement: ['', Validators.maxLength(30)],
    district: ['', Validators.compose([Validators.required, Validators.maxLength(60)])],
    state: ['', Validators.required],
    city: ['', Validators.compose([Validators.required, Validators.maxLength(70)])]
  }),
  status: [true],
  created_at: [new Date()],
  updated_at: [new Date()]
});

Here is template:

<form [formGroup]="shopGroup">
  <mat-horizontal-stepper [linear]="isLinear" #stepper>
    // Im not sure how to set stepControl
    <mat-step [stepControl]="?">
        <ng-template matStepLabel>Store Creation</ng-template>
        <mat-form-field>
          <input matInput placeholder="Nome" formControlName="name">
        </mat-form-field>
        ...
        <div>
          <button mat-button matStepperNext type="button">Next</button>
        </div>
    </mat-step>
    // Im not sure how to set stepControl
    <mat-step formGroupName="address" [stepControl]="?">
      <ng-template matStepLabel>Configuração do Envio/Frete</ng-template>
      <mat-form-field>
        <input matInput placeholder="CEP" formControlName="zipcode">
      </mat-form-field>
      ...
      <div>
        <button mat-button matStepperPrevious>Back</button>
        <button mat-button matStepperNext>Next</button>
      </div>
    </mat-step>
    <mat-step>
      <ng-template matStepLabel>Done</ng-template>
      You are now done.
      <div>
        <button mat-button matStepperPrevious>Back</button>
      </div>
    </mat-step>
  </mat-horizontal-stepper>
</form>

This is the Angular Material documentation for single forms:

<form [formGroup]="formGroup">
  <mat-horizontal-stepper formArrayName="formArray" linear>
    <mat-step formGroupName="0" [stepControl]="formArray.get([0])">
      ...
      <div>
        <button mat-button matStepperNext type="button">Next</button>
      </div>
    </mat-step>
    <mat-step formGroupName="1" [stepControl]="formArray.get([1])">
      ...
      <div>
        <button mat-button matStepperPrevious type="button">Back</button>
        <button mat-button matStepperNext type="button">Next</button>
      </div>
    </mat-step>
    ...
  </mat-horizontal-stepper>
</form>

I want to use shopGroup on first step, then use address (group inside shopGroup) on second step. Finally, i want to send shopGroup. I'm aware that I need to set type="button" between steps, and type="submit" on the end, however i'm not sure how to set [stepControl] to move from one step to another one. How to make it work on template (html)?

解决方法

You can read in official docs how you should handle a mat-stepper with a single form

First you need to define an array fo form groups:

this.formGroup = this._formBuilder.group({
      formArray: this._formBuilder.array([
        this._formBuilder.group({
          firstNameFormCtrl: ['', Validators.required],
          lastNameFormCtrl: ['', Validators.required],
        }),
        this._formBuilder.group({
          emailFormCtrl: ['', Validators.email]
        }),
      ])
    });

Second you need be able to return the array of formGroups that will be consumed on HTML template:

  get formArray(): AbstractControl | null {
    return this.dictationForm.get('formArray');
  }

Then you should associate each mat-step with a particular group formArray element:

<mat-step formGroupName="0" [stepControl]="formArray?.get([0])"></mat-step>

You can find a working example here

相似信息