Angular动态生成文本框如何向自定义验证器传递遍历项属性
解决方案
首先修正你现有代码的两个基础问题:
- 所有动态生成的文本框共用同一个
FormControl实例,导致任意一个控件触发校验全列表都会生效,每个输入项需要对应独立的FormControl实例 - 模板中
*ngFor语法错误,let computer in _Computers要改为let computer of _Computers
1. 改造自定义验证器支持传参
调整验证器函数为高阶函数,外层接收你需要传入的Optional、Id等参数,内层返回实际校验逻辑:
// 可接收任意自定义参数,包括computer的Id、Optional属性等 customValidator(isOptional: boolean, computerId?: number) { return (control: AbstractControl): { [key: string]: boolean } | null => { // 可选项直接跳过非空校验 if (isOptional) { return null; } // 必选项才校验非空 if (!control.value?.trim()) { return { 'textRequired': true }; } // 如果需要用到computerId做其他校验逻辑,直接在这里使用即可 return null; }; }
2. 为每个computer生成独立的FormControl
初始化列表时遍历所有项,给每个项生成专属的FormControl,同时把当前项的参数传入验证器:
// 如果你不想修改原computer对象,也可以用FormArray来管理所有控件 _Computers: any[] = []; ngOnInit() { // 假设此处是你获取_Computers列表的逻辑 this._Computers = this._Computers.map(item => { return { ...item, // 把当前项的Optional、Id传入验证器 frmCtrl: new FormControl('', this.customValidator(item.Optional, item.Id)) } }) }
3. 修正模板绑定
调整模板中表单控件的绑定逻辑,绑定每个项独立的FormControl,同时动态生成name属性避免表单同名冲突:
<tr *ngFor="let computer of _Computers; let i = index;"> <td>{{computer.Name}}</td> <td>{{computer.Optional}}</td> <td> <input matInput [formControl]="computer.frmCtrl" name="UnitofPrice_{{i}}" [(ngModel)]="computer.inputValue"> </td> <td>{{computer.UnitofPrice}}</td> </tr>
如果更偏好使用FormArray管理批量控件,也可以按以下方式实现:
computerFormArray: FormArray = new FormArray([]); ngOnInit() { this._Computers.forEach(item => { this.computerFormArray.push( new FormControl('', this.customValidator(item.Optional, item.Id)) ) }) }
模板绑定改为:
<input matInput [formControl]="computerFormArray.at(i)" name="UnitofPrice_{{i}}" [(ngModel)]="computer.inputValue">
内容的提问来源于stack exchange,提问作者Billy
相关产品推荐
相关产品推荐

