如何在Angular 9 ReactiveForm中获取嵌套的FormArray控件
编辑 由于上面Chellappan的回答,问题的第一部分得以解决,但我遇到了其他问题,这使得我进行了stackblitz,可以在这里找到: 问题是我无法正确检索从表单中选择的产品列表,因为它们都已输出:如何在Angular 9 ReactiveForm中获取嵌套的FormArray控件,angular,typescript,angular-reactive-forms,formarray,Angular,Typescript,Angular Reactive Forms,Formarray,编辑 由于上面Chellappan的回答,问题的第一部分得以解决,但我遇到了其他问题,这使得我进行了stackblitz,可以在这里找到: 问题是我无法正确检索从表单中选择的产品列表,因为它们都已输出: "courses": [ { "courseName": "Dessert", "products": [ { "product": true }, { "product
"courses": [
{
"courseName": "Dessert",
"products": [
{
"product": true
},
{
"product": false
},
{
"product": null
}
]
我不知道如何检索类似以下内容:
"courses": [
{
"courseName": "Dessert",
"products": [
{
"Crumble aux pommes": true
},
{
"Mousse au chocolat maison": false
},
{
"Riz au lait": false
}
]
第二个问题是我的复选框的标签不是独立的。如果我添加了一个新的“课程”并选择了一些产品,那么其他课程中所有复选框的标签也会更改
我希望我的帖子不要太乱,我不会经常在堆栈溢出上编辑消息
编辑结束
我有一个带有嵌套表单数组的反应式表单来描述包含多个课程的菜单 每门课程都包含几个产品,但我不知道如何让它发挥作用。 我的实际问题是,我无法检索第二级控件 以下是菜单的json结构:
{
"name": "",
"description": "",
"price": "",
"courses": [
{
"courseName": "",
"products": [
{
"product": ""
}
]
}
]
}
我以这个项目为例:
为了便于阅读,以下是我的简化表格:
添加课程
{{course.name}
加载产品//{
这个类别=结果;
},
错误=>{
console.log(错误);
此参数为.categories=[];
});
this.initForm();
}
initForm(){
this.menuForm=新表单组({
名称:新FormControl(“”,[Validators.required,Validators.maxLength(100)],
描述:新FormControl(“”,Validators.maxLength(255)),
价格:新FormControl(“”,[Validators.required,Validators.min(0)]),
课程:新形式([
this.initCourse(),
])
});
}
initCourse(){
返回新表单组({
courseName:新表单控件(“”),
产品:新FormArray([
this.initProduct()
])
});
}
initProduct(){
返回新表单组({
产品:新FormControl(“”)
});
}
课程(表格){
返回表单.controls.courses.controls;
}
getProducts(表格){
返回表单.controls.products.controls;
}
onAddCourse(){
const control=this.menuForm.get('courses')作为FormArray;
control.push(this.initCourse());
}
在线产品(i:编号){
log(this.menuForm.controls.courses);
const courseControl=this.menuForm.get('courses')作为FormArray;
const course=courseControl.at(i).get('courseName').value;
控制台日志(课程);
const products:ProductModel[]=this.mapProducts.get(课程);
控制台日志(产品);
const productControl=this.menuForm.get('courses').get[i].get('products')作为FormArray;
onSubmit(菜单格式:FormGroup){
...
}
...
}
如果我像那样离开后端,我有一个错误:
Cannot read property 'controls' of undefined at MenuEditComponent.getProducts
因此,我的“产品”FormArray未初始化。
如果我这样做:
getProducts(表单){
返回表单。控件。产品?控件;
}
我不再有错误,但我无法访问产品formControls。
如果我尝试:
onLoadProducts(i:编号){
const courseControl=this.menuForm.get('courses')作为FormArray;
const course=courseControl.at(i).get('courseName').value;
const products:ProductModel[]=this.mapProducts.get(课程);
const productControl=this.menuForm.get('courses').get[i].get('products')作为FormArray;
//在最后一行,我得到了一个'cannotreadproperty'get'of undefined'
...
}
我做错了什么?为什么我的“产品”FormArray未初始化
非常感谢你的帮助 课程是formGroup的数组,在formGroup products中是另一个formArray,因此您必须将单个课程formGroup传递给getProducts方法 component.html
<div class="row" formArrayName="courses">
<div *ngFor="let course of getCourses(menuForm); let i = index" [formGroupName]="i">
<div class="...">
<select class="form-control" formControlName="courseName">
[value]="course"
<option *ngFor="let course of courses">{{ course.name }}</option>
</select>
<button type="button" class="mt-2 btn btn-outline-dark" (click)="onLoadProducts(i)">
Load Products
</button>
<div class="row" formArrayName="products">
<div class="col-md-12" *ngFor="let product of getProducts(course); let j = index" [formGroupName]="j">
<input class="form-check-input" type="checkbox" id="product{{ i }}-{{ j }}" formControlName="product" />
<label class="form-check-label" for="product{{ i }}-{{ j }}">product</label>
</div>
</div>
</div>
</div>
</div>
我查看了您的stackblitz,并对其进行了修改,使其正常工作。您不需要将formControlName与产品绑定,因为您不是从前端UI设置它们,而是选择它们。我在类
ProductModel
中添加了一个名为added
的字段,然后我刚刚为复选框实现了change
事件,以将其标记为true或false
您还可以看到我如何设置产品的值。当您点击加载产品
按钮时,您正在添加空的表单组
,但您还应该使用产品数据在其中设置产品
控件。您可以在代码中看到我是如何在LoadProducts方法中执行此操作的
之后,您可以在产品循环中看到我是如何获得产品字段的。循环实际上给了我们FormGroup,我们必须从中获取产品字段值
这是正在进行的stackblitz
你可以特别注意这一部分
if (this.productsByCategory) {
this.productsByCategory.forEach(
(product) => {
const productForm: FormGroup = this.initProduct();
productForm.controls.product.setValue(product);
control.push(productForm);
});
}
创建productFormGroup后,还应在其中设置产品。比如productForm.controls.product.setValue(product)代码>
然后在前端你可以看到
<div *ngFor="let p of getProducts(course); let j = index" [formGroupName]="j">
<input type="checkbox" id="product{{i}}-{{j}}" [value]="p.value.product.added" (change)="p.value.product.added = !p.value.product.added"/>
<label for="product{{i}}-{{j}}">{{p.value.product.name}}</label>
</div>
{{p.value.product.name}
您应该将值绑定到产品的added属性,并且名称也应该显示在产品对象的标签中
希望这将有助于您进一步进行
第二个问题是我的复选框的标签不是独立的。如果我添加了一个新的“课程”并选择了一些产品,那么其他课程中所有复选框的标签也会更改
上述问题已得到解决
我不知道如何检索类似以下内容:
而不是productName:true/false
您有整个产品对象可用,并且
<div *ngFor="let p of getProducts(course); let j = index" [formGroupName]="j">
<input type="checkbox" id="product{{i}}-{{j}}" [value]="p.value.product.added" (change)="p.value.product.added = !p.value.product.added"/>
<label for="product{{i}}-{{j}}">{{p.value.product.name}}</label>
</div>