如何在自定义校验器中获取动态创建的表单组内所有表单控件
解决方案:动态表单count字段总和校验
编写自定义校验器
针对你的需求,需要一个能访问整个表单数组的校验器,计算所有count字段的总和是否超过availableCount。可选择两种校验方式:- 表单数组级校验器(全局校验)
import { AbstractControl, FormArray, ValidationErrors, ValidatorFn } from '@angular/forms'; export function totalCountValidator(availableCount: number): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { const fieldsArray = control as FormArray; if (!fieldsArray || fieldsArray.controls.length === 0) return null; const total = fieldsArray.controls.reduce((sum, fieldGroup) => { const countValue = fieldGroup.get('count')?.value || 0; return sum + parseInt(countValue, 10); }, 0); return total > availableCount ? { totalExceeded: { max: availableCount, currentTotal: total } } : null; }; }- 单个控件级校验器(针对当前输入控件)
export function countFieldValidator(availableCount: number): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { // 从当前控件向上获取父级表单数组 const fieldsArray = control.parent?.parent as FormArray; if (!fieldsArray) return null; const total = fieldsArray.controls.reduce((sum, fieldGroup) => { const countValue = fieldGroup.get('count')?.value || 0; return sum + parseInt(countValue, 10); }, 0); return total > availableCount ? { countExceedsTotal: true } : null; }; }绑定校验器到表单
- 给表单数组添加全局校验器
在初始化表单时,将校验器传入表单数组的配置参数:
this.myForm = this.fb.group({ fieldsArray: this.fb.array([], [totalCountValidator(this.availableCount)]) });- 给单个count控件添加校验器
在创建表单组的方法中,为count字段绑定校验器:
createFieldGroup(): FormGroup { return this.fb.group({ name: ['', Validators.required], count: ['', [ Validators.required, Validators.min(0), countFieldValidator(this.availableCount) ]] }); }- 给表单数组添加全局校验器
触发动态控件变更后的校验
当添加或删除表单控件时,手动触发表单数组的校验状态更新:addField() { const fieldsArray = this.myForm.get('fieldsArray') as FormArray; fieldsArray.push(this.createFieldGroup()); fieldsArray.updateValueAndValidity({ emitEvent: true }); } removeField(index: number) { const fieldsArray = this.myForm.get('fieldsArray') as FormArray; fieldsArray.removeAt(index); fieldsArray.updateValueAndValidity({ emitEvent: true }); }模板中显示错误提示
- 全局错误提示(对应表单数组校验器)
<div *ngIf="myForm.get('fieldsArray')?.hasError('totalExceeded')" class="error-message"> 总数量超过可用值 {{ myForm.get('fieldsArray')?.getError('totalExceeded').max }},当前总和为 {{ myForm.get('fieldsArray')?.getError('totalExceeded').currentTotal }} </div>- 单个控件错误提示(对应控件级校验器)
<mat-form-field *ngFor="let field of fieldsArray.controls; let i = index"> <input matInput formControlName="count" placeholder="Count"> <mat-error *ngIf="field.get('count')?.hasError('countExceedsTotal')"> 当前输入后总数量超过可用值 {{ availableCount }} </mat-error> </mat-form-field>
内容的提问来源于stack exchange,提问作者KcH
相关产品推荐
相关产品推荐

