【问题标题】:Angular - How to Validate each step in Angular Material stepperAngular - 如何验证 Angular Material stepper 中的每一步
【发布时间】:2021-07-22 14:03:03
【问题描述】:

在 Angular-12 中,我正在实现 Material Stepper。它有两 (2) 个步骤:

组件:

export class SignupCompanyComponent implements OnInit {
  isLinear = true;
  isLoading = false;
  companySetupForm!: FormGroup;
  companyForm!: FormGroup;
  idForm!: FormGroup;

  ngOnInit() {
    this.companyForm = this.fb.group({
      companyName: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(100)]]
    });
    this.idForm = this.fb.group({
      registrationNumber: ['', [Validators.required, Validators.maxLength(100)]],
    });
  }

  get fc() {
    return this.companyForm.controls;
  };
  get fi() {
    return this.idForm.controls;
  };

  onSubmit() {}
}

HTML:

<mat-horizontal-stepper [linear]="isLinear" #stepper labelPosition="bottom">
  <mat-step [stepControl]="companyForm">
    <form [formGroup]="companyForm">
      <ng-template matStepLabel matStepperIcon="phone">Company Info</ng-template>

      <div class="col-12 col-md-12">
        <div class="form-group">
          <label for="name">Company Name:<span style="color:red;">*</span></label>}
          <input type="text" formControlName="companyName" placeholder="Company Name" class="form-control" required/>
        </div>
        <div *ngIf="fc.companyName.touched && fc.companyName.invalid">
          <div *ngIf="fc.companyName.hasError('required')">
            <div class="text-danger">
              Company Name is required!
            </div>
          </div>
          <div *ngIf="fc.companyName.hasError('minlength')">
            <div class="text-danger">
              Company Name cannot be less than 3 characters!
            </div>
          </div>
          <div *ngIf="fc.companyName.hasError('maxlength')">
            <div class="text-danger">
              Company Name cannot be more than 100 characters!
            </div>
          </div>
        </div>
      </div>
      <div class="card-footer">
        <button mat-raised-button color="primary" matStepperNext>Next</button>
      </div>
    </form>
  </mat-step>
  <mat-step [stepControl]="idForm">
    <form [formGroup]="idForm">
      <ng-template matStepLabel>Company ID</ng-template>
      <div class="col-12 col-md-4">
        <div class="form-group">
          <label for="registration_number">Registration Number:<span style="color:red;">*</span></label>
          <input type="text" formControlName="registrationNumber" placeholder="Registration Number" class="form-control" required/>
        </div>
        <div *ngIf="fi.registrationNumber.touched && fi.registrationNumber.invalid">
          <div *ngIf="fi.registrationNumber.hasError('required')">
            <div class="text-danger">
              Company Reg. No. is required!
            </div>
          </div>
          <div *ngIf="fi.registrationNumber.hasError('maxlength')">
            <div class="text-danger">
              Company Reg. No. cannot be more than 100 characters!
            </div>
          </div>
        </div>
      </div>
      <div class="card-footer">
        <button mat-raised-button color="black" matStepperPrevious>Back</button> &nbsp;
        <button mat-raised-button color="success" [disabled]="isLoading" type="submit" (click)="onSubmit()">
                <span *ngIf="isLoading" class="spinner-border spinner-border-sm mr-1"></span>
                  Submit
              </button> &nbsp;
        <button mat-raised-button color="warn" (click)="stepper.reset()">Reset</button>
      </div>
  </mat-step>
</mat-horizontal-stepper>

当触摸每个 formControl 时,Material Stepper 工作正常。它立即显示错误。 但是当点击Next Button时,Step1(companyForm)中没有数据填写,虽然没有移动到下一步或表单,但是没有报错。

我希望它验证每个步骤并在触摸每个表单控件时显示。

我如何做到这一点?

谢谢

【问题讨论】:

    标签: angular


    【解决方案1】:

    Material 似乎没有将表单标记为已触摸,因此我将重新绑定按钮:

    <button mat-raised-button color="primary" (click)="onFirstStepDone()">Next</button>
    

    在组件中,您需要对步进器的引用:

    @ViewChild('stepper') stepper: MatHorizontalStepper;
    
    onFirstStepDone() {
       if(!this.companyForm .valid) {
           // this should make all invalid fields light up in red
           this.companyForm.markAllAsTouched();
           return;
       }
       this.stepper.next();
    }
    

    【讨论】:

      【解决方案2】:

      我做的两件事是将字段验证设置为onBlur like;

      this.companyForm = this.fb.group({
            companyName: ['',
                         [Validators.required,
                          Validators.minLength(3),
                          Validators.maxLength(100)]]
          },
          { updateOn: "blur" });
      

      ...我个人不喜欢在必填字段有效之前允许继续,所以我将步进按钮设置为禁用,直到它喜欢为止;

      <button mat-raised-button
              color="primary"
              matStepperNext
              [disabled]="companyForm.status != 'VALID'">
         Next
      </button>
      

      或者一定要看看Manhattan先生的评论来验证最后的表格,你可以通过将上面的{ updateOn: "blur" }blur更改为submit来完成同样的事情

      【讨论】:

      • 老实说,我只是重新绑定按钮,如果无效 => markAllAsTouched(),如果有效 => stepper.next(),这样会引起用户的注意错误.. .这似乎也更接近提问者的用例
      • @Mr.Manhattan 是的,这也是一个好方法,也许提供一个示例答案会对其他人有所帮助。
      • 你已经回答了,所以我不想偷你的节目:)
      • @Mr.Manhattan 直到我们可以用积分兑换奖品或其他不那么重要的东西,帮助人们比 SO 积分更有价值:D
      • @Mr.Manhattan - 你能解释一下你的方法或简单的例子吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-08
      • 1970-01-01
      • 2020-05-18
      • 2022-08-05
      • 1970-01-01
      • 1970-01-01
      • 2018-07-14
      相关资源
      最近更新 更多