如何获取自定义验证器中的所有表单控件(动态创建的字段组)

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

我正在使用表单生成器构建动态表单,如下所示:

到目前为止我一直在 stackblitz

中尝试的可运行代码

我已阅读文档并看到了此例如,但找不到获取其他动态添加的表单控件值并对其执行某些操作的示例..

这里我想检查当前输入的计数字段和其余计数字段的总和是否小于

availableCount
...如果大于我想显示/返回错误并使当前控件无效

我理解从 customValidator 返回对象的部分,但是我在上面的代码中尝试的方式是在从表单获取 feildsArray 时出错,但不确定我缺少什么..

我也接受了人工智能的帮助,但无法得到正确的结果...任何帮助表示感谢,谢谢

angular angular-material angular-reactive-forms
1个回答
0
投票

如果你看一下代码,你已经声明了

myForm: FormGroup
但你还没有用值初始化它,所以初始值将是
undefined
,所以验证器函数试图访问未定义的属性并抛出错误,我们可以使用
?.
,这是打字稿安全检查,它将执行自动空检查并防止此类错误。

片段

  countFieldValidator(control: FormControl) {
    const fieldsArray = this.myForm?.get('fieldsArray') as FormArray; // <- changed here!
    const totalCount = fieldsArray?.controls // <- changed here!
      .map((fieldGroup) => fieldGroup.get('count')?.value) // <- changed here!
      .reduce((sum, count) => sum + (count || 0), 0);

    if (totalCount > this.availableCount) {
      return { countExceeded: true };
    }
    return null;
  }

游乐场安全检查示例

ts

import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import {
  FormBuilder,
  FormGroup,
  Validators,
  FormControl,
  FormArray,
} from '@angular/forms';

@Component({
  selector: 'app-forms',
  templateUrl: './forms.component.html',
  styleUrls: ['./forms.component.scss'],
  encapsulation: ViewEncapsulation.None,
})
export class FormsComponent {
  myForm: FormGroup;
  availableCount = 100; // Set the available count limit here

  constructor(private fb: FormBuilder) {
    this.myForm = this.fb.group({
      fieldsArray: this.fb.array([this.createFieldGroup()]),
    });
  }

  createFieldGroup(): FormGroup {
    const newFieldGroup = this.fb.group({
      count: [
        null,
        [
          Validators.required,
          Validators.min(1),
          this.countFieldValidator.bind(this),
        ],
      ],
      group: [null, Validators.required],
    });
    return newFieldGroup;
  }

  get fieldsArray() {
    return this.myForm.get('fieldsArray') as FormArray;
  }

  countFieldValidator(control: FormControl) {
    const fieldsArray = this.myForm?.get('fieldsArray') as FormArray;
    const totalCount = fieldsArray?.controls
      .map((fieldGroup) => fieldGroup.get('count')?.value)
      .reduce((sum, count) => sum + (count || 0), 0);

    if (totalCount > this.availableCount) {
      return { countExceeded: true };
    }
    return null;
  }

  addFields(): void {
    this.fieldsArray.push(this.createFieldGroup());
  }

  removeFields(index: number) {
    this.fieldsArray.removeAt(index);
  }
}

html

<form [formGroup]="myForm" class="form-container">
  <div formArrayName="fieldsArray" class="form-group-container">
    <div
      *ngFor="let fieldGroup of fieldsArray.controls; let i = index"
      [formGroupName]="i"
      class="form-group"
    >
      <mat-form-field class="count-field">
        <mat-label>Count</mat-label>
        <input formControlName="count" type="number" matInput />
        <mat-error *ngIf="fieldGroup?.controls?.count?.errors?.required">
          Field is mandatory
        </mat-error>
        <mat-error
          *ngIf="
            !fieldGroup?.controls?.count?.errors?.required &&
            fieldGroup?.controls?.count?.errors?.countExceeded
          "
        >
          Sum of inputs exceeds 100, kindly reduce the value(s)
        </mat-error>
      </mat-form-field>
      <button class="remove-button" (click)="removeFields(i)">delete</button>
    </div>
  </div>
  <button type="button" label="Add" (click)="addFields()">Add</button>
</form>

Stackblitz 演示

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