我正在构建一个动态表单,使用如下所示的表单构建器:

可运行代码我一直在try 到目前为止stackblitz

我读过文档,看到了这e.g.,但找不到一个例子,其中其他动态添加的表单控件值被提取并对它们做一些操作.

这里I wanted to check the sum of current entered count field and the rest of the count fields is less than the 100 ... If it is greater I wanted to show / return an error and make the current control invalid

我理解了从customValidator返回对象的部分,但我在上面的代码中try 的方式是在从form获取feildsArray时给了我错误,不知道我错过了什么.

我也接受了人工智能的帮助,但无法正确地处理...感谢任何帮助,谢谢.

推荐答案

如果你看一下代码,你已经声明了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;
  }

safe check example in playground

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 Demo

Angular相关问答推荐

Angular :将动态创建的零部件附加为目标元素的子项

try 测试具有Angular material 下拉列表的组件时,在Angular 17中发现&q;错误的意外合成属性@TransitionMessages

第15角Cookie的单元测试用例

首期日历发行

使用Angular 13的NgxPrinterService打印时,第二页上的空白区域

使用`UrlHandlingStrategy`更改位置

如何防止变量值重置?

Angular 17水化-POST请求同时触发客户端/服务器端,而GET请求仅触发服务器端?

Angular 组件存储,为什么我的效果可以';在http错误后不会被触发?

使用 RXJS 进行空闲/不活动跟踪

在 kubernetes 上创建 Ingress 服务以将 springboot [后端] 连接到前端 [angular]

如何更改 Angular material 按钮中的内部 RippleColor 和 UnboundedRipple 效果?

当访问令牌在 MSAL for Angular 中过期时如何重定向用户?

Angular 无法从后端获取数据到前端

res.json() 不是函数

如何在插值中编写条件?

在Angular2的 Select 列表中设置最初 Select 的项目

Angular2 中的providers提供者是什么意思?

如何在 Angular 6 中使用 mouseover 和 mouseout

实现autocomplete功能