Angular 8-添加动态表单组后如何防止反应式表单验证?

问题描述 投票:0回答:1

我已经创建了可重复使用的组件,用于创建/编辑我的应用程序的实体。该组件具有一个反应形式,其中包含一些动态部分。

整个表单按预期工作,但是我遇到了验证问题:每当我单击按钮以向表单添加动态表单组时,都会添加显示验证错误的表单。同样,不仅验证了动态部分,还验证了表单的其余部分。

[似乎添加了动态部分,正在执行验证,就像按下了提交按钮一样,但是没有。

我想要实现的是能够添加动态formGroup,而无需执行此操作本身就可以执行表单的验证。

我想漏点吗?

import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {AbstractControl, FormArray, FormControl, FormGroup, Validators} from '@angular/forms';
import {Plan} from '../shared/domain/plan.model';
import {Milestone} from '../shared/domain/milestone.model';

@Component({
  selector: 'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {

  @Input() plan?: Plan;

  planForm = new FormGroup({
    id: new FormControl(
      null,
      [
        Validators.required,
        Validators.minLength(4),
        Validators.pattern('^[a-zA-Z0-9_-]+$')
      ]
    ),
    milestones: new FormArray([])
  });

  constructor() {}

  ngOnInit() {
    this.fillForm();
  }

  fillForm() {
    this.planForm.get('id').setValue(this.plan ? this.plan.getId() : '');
    this.createMilestoneFormControls();

    if (this.plan) {
      this.planForm.get('id').disable();
    }
  }

  createMilestoneFormControls() {
    if (!this.plan) {
      this.addMilestoneToFormArray();
      return;
    }

    this.plan.getMilestones().forEach((milestone: Milestone) => {
      this.addMilestoneToFormArray(milestone);
    });
  }

  addMilestoneToFormArray(milestone?: Milestone) {
    const milestonesFormArray = this.milestonesFormArray;
    milestonesFormArray.push(new FormGroup({
      description: new FormControl(milestone ? milestone.getDescription() : ''),
      startDate: new FormControl(
        milestone ? milestone.getStartDate().toISOString().substring(0, 10) : '',
        [Validators.required]
      ),
      endDate: new FormControl(
        milestone ? milestone.getEndDate().toISOString().substring(0, 10) : '',
        [Validators.required]
      ),
    }));
  }

  get milestonesFormArray() {
    return this.planForm.get('milestones') as FormArray;
  }

  removeMilestoneFromFormArray(i: number) {
    this.milestonesFormArray.removeAt(i);
  }

  getValidationMessage(field: string, fault: string): string {
    return this.validationMessages[field][fault];
  }

  getDateInputValidationMessage(fieldName: string, control: AbstractControl): string {

    if (control.errors.matDatepickerMax) {
      return this.getValidationMessage(fieldName, 'matDatepickerMax');
    }

    if (control.errors.matDatepickerParse) {
      return this.getValidationMessage(fieldName, 'matDatepickerParse');
    }

    if (!control.value && control.errors.required) {
      return this.getValidationMessage(fieldName, 'required');
    }

    return '';
  }

}
<form [formGroup]="planForm" (keydown.enter)="$event.preventDefault()">
    <mat-form-field class="formInput" appearance="outline">
    <mat-label>Relationship identifier</mat-label>
    <input matInput formControlName="id" autocomplete="off" required>
    <mat-error *ngIf="planForm.get('id').invalid">
      <div *ngIf="planForm.get('id').errors.required">{{getValidationMessage('id', 'required')}}</div>
      <div *ngIf="planForm.get('id').errors.minlength">{{getValidationMessage('id', 'minlength')}}</div>
      <div *ngIf="planForm.get('id').errors.pattern">{{getValidationMessage('id', 'pattern')}}</div>
    </mat-error>
  </mat-form-field>
  <div formArrayName="milestones">
    <div *ngFor="let milestone of milestonesFormArray.controls; let i=index"
      [formGroupName]="i.toString()"
      class="milestoneFormBlock">

      <div class="mobile">Milestone #{{i+1}}</div>
      <hr class="milestoneDivider">
      <mat-form-field class="formInputMilestone" appearance="outline" style=" margin-bottom: -1.25em">
        <mat-label>Description</mat-label>
        <input matInput formControlName="description" autocomplete="off">
      </mat-form-field>

      <mat-form-field class="formInputMilestone" appearance="outline" style=" margin-bottom: -1.25em">
        <mat-label>Start Date</mat-label>
        <input
          matInput
          [matDatepicker]="milestoneStartDate"
          formControlName="startDate"
          autocomplete="off"
          required
          placeholder="mm/dd/yyyy"
          [max]="milestone.get('endDate').value">
        <mat-datepicker-toggle matSuffix [for]="milestoneStartDate"></mat-datepicker-toggle>
        <mat-datepicker #milestoneStartDate></mat-datepicker>
        <mat-error *ngIf="milestone.get('startDate').invalid">
          <div>{{getDateInputValidationMessage('startDate', milestone.get('startDate'))}}</div>
        </mat-error>
      </mat-form-field>

      <mat-form-field class="formInputMilestone" appearance="outline" style=" margin-bottom: -1.25em">
        <mat-label>End Date</mat-label>
        <input
          matInput
          [matDatepicker]="milestoneEndDate"
          formControlName="endDate"
          autocomplete="off"
          required
          placeholder="mm/dd/yyyy"
          [min]="milestone.get('startDate').value">
        <mat-datepicker-toggle matSuffix [for]="milestoneEndDate"></mat-datepicker-toggle>
        <mat-datepicker #milestoneEndDate></mat-datepicker>
        <mat-error *ngIf="milestone.get('endDate').invalid">
          <div>{{getDateInputValidationMessage('endDate', milestone.get('endDate'))}}</div>
        </mat-error>
      </mat-form-field>

      <button class="remove-milestone-btn" mat-raised-button color="warn" (click)="removeMilestoneFromFormArray(i)">
        <fa-icon [icon]="['fas', 'trash']"></fa-icon>
      </button>

    </div>
    <button class="add-milestone-btn" mat-fab color="primary" (click)="addMilestoneToFormArray()">
      <fa-icon [icon]="['fas', 'plus']"></fa-icon>
    </button>
  </div>

  <button class="submitBtn" (click)="onSubmit()" mat-raised-button color="primary">
    <div *ngIf="plan; then thenBlock else elseBlock"></div>
    <ng-template #thenBlock>Update relationship</ng-template>
    <ng-template #elseBlock>Create relationship</ng-template>
  </button>

</form>
angular forms validation angular-forms
1个回答
1
投票

如果未指定按钮,则将其视为type='submit'。因此,表单确实接收到submit事件。

不是在单击按钮时打算将提交时的按钮更改为<button type="button">

© www.soinside.com 2019 - 2024. All rights reserved.