angular - 我在 FormArray 上做错了什么?
问题描述
在我的表单中,我将包含以下元素:
- 输入(复选框)
- 代码(跨度)
- 名称(跨度)
这些值来自服务器,这就是为什么它是动态添加的。
但是,我的算法面临以下问题:
core.js: 6228 ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
只有这个错误没有意义,因为控制台正确地显示了值并且这个家伙是一个数组:
主要部件
@Component({
selector: 'zx-create-country-form',
templateUrl: './create-country-form.component.html',
styleUrls: ['./create-country-form.component.scss'],
})
export class CreateCountryFormComponent implements OnInit {
createCountryForm!: FormGroup;
dataTemp = [
{
code: 'BR',
name: {
pt_BR: 'Brasil',
},
},
{
code: 'TST',
name: {
pt_BR: 'tst3',
},
},
];
constructor(protected readonly componentService: ComponentService, protected readonly formBuilder: FormBuilder) {
this.createCountryForm = formBuilder.group({
countries: formBuilder.array(this.addCountries()),
});
}
ngOnInit(): void {}
addCountries(): FormGroup[] {
const formsGroups: FormGroup[] = [];
this.dataTemp.map(country => {
formsGroups.push(
this.formBuilder.group({
radio: this.formBuilder.control([{ value: false, disabled: true }], [Validators.requiredTrue]),
code: this.formBuilder.control(country.code, [Validators.required, Validators.minLength(1), Validators.maxLength(2)]),
name: this.formBuilder.control(country.name.pt_BR),
})
);
});
return formsGroups;
}
}
子组件
<zx-form [fmGroup]="fmGroup">
<div [formArrayName]="fmArrayName" *ngFor="let country of fmGroup.controls.countries; let i = index">
<div [formGroupName]="i">
<input formControlName="radio" placeholder="Item name" />
<input formControlName="code" placeholder="Item name" />
<input formControlName="name" placeholder="Item name" />
eqqe
</div>
</div>
</zx-form>
解决方案
再见
countries: formBuilder.array(this.addCountries()),
this.addCountries 必须返回一个 FormGroups 数组。如果你使用map,你会在witch element中得到一个新数组,它是原始数组的变换。所以
return this.dataTemp.map(country =>
this.formBuilder.group({
radio: this.formBuilder.control([{ value: false, disabled: true }], [Validators.requiredTrue]),
code: this.formBuilder.control(country.code, [Validators.required, Validators.minLength(1), Validators.maxLength(2)]),
name: this.formBuilder.control(country.name.pt_BR),
})
);
使用 forEach,您可以循环遍历数组并为每个元素制作“一些东西”,就像您尝试的那样
const formsGroups: FormGroup[] = [];
this.dataTemp.forEach(country => {
formsGroups.push(
this.formBuilder.group({
radio: this.formBuilder.control([{ value: false, disabled: true }], [Validators.requiredTrue]),
code: this.formBuilder.control(country.code, [Validators.required, Validators.minLength(1), Validators.maxLength(2)]),
name: this.formBuilder.control(country.name.pt_BR),
})
);
});
还有一点需要注意的是如何在.html中进行迭代,需要遍历表单Array的控件,为此,创建一个数组的getter
get myArrayForm()
{
return this.fmGroup.get('fmArrayName') as FormArray
}
并遍历 myArrayForm.controls,但取出 formArray 名称,并看到它没有被 [] 包围
<div formArrayName="fmArrayName">
<div *ngFor="let country of myArrayForm.controls; let i = index">
<div [formGroupName]="i">
<input formControlName="radio" placeholder="Item name" />
<input formControlName="code" placeholder="Item name" />
<input formControlName="name" placeholder="Item name" />
eqqe
</div>
</div>
</div>
确实在官方文档中解释得不好,但你可以看到,例如这个 Netanel Basal 的条目
如果数组的至少一个元素为真,则更新为验证器,我们需要为自己的数组创建自定义验证,您可以在自己的组件中创建验证器
atLeastOne()
{
return (formArray:FormArray)=>{
return formArray.value && formArray.value.filter(x=>x.radio).length<=0?
{error:"At least one"}:null
}
}
并且在创建表单时使用
createCountryForm = this.formBuilder.group({
countries: this.formBuilder.array(this.addCountries(), this.atLeastOne())
});
注意:当我们在 FormArray 上创建自定义验证器时,我们需要考虑到每次 formArray(或任何此 FormGroups 或 Forms 控件更改)时都会检查它
推荐阅读
- c# - 替代 StreamReader.ReadLine(filepath) 以避免内存不足?
- ios - Flutter iOS 存档版本在 Xcode 中获取“xx plugin.h”文件未找到错误
- c - 简单 C 计算器中的分段错误
- c++ - 使用三元运算符并删除移动/复制 ctor 时,Visual Studio 不执行 RVO
- javascript - 谷歌地图中标记的打开和关闭切换按钮反应
- php - 如何在爬取中使用 dom xpath?
- python - 如何使用 pysftp/paramiko 在 python 中启用键盘交互式身份验证?
- playframework - 如何从文件系统提供静态资产而不是默认资产 JAR 包(Play 框架)
- python - 无法在 Mac OS Mojave 上导入海龟(版本 10.14.2)
- javascript - 从另一个页面上的 HTML 表单访问值