gpt4 book ai didi

angular - 如何在 Angular 9 Reactive Form 中获取嵌套的 FormArray 控件

转载 作者:行者123 更新时间:2023-12-04 16:40:11 24 4
gpt4 key购买 nike


编辑

由于上面 Chellappan 的回答,问题的第一部分已经解决,但我遇到了其他问题,这让我做了一个可以在这里找到的 stackblitz: https://stackblitz.com/edit/angular-ivy-bzh3dh

问题是我无法正确检索从表单中选择的产品列表,因为它们都已输出:

  "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
}
]

第二个问题是我的复选框的标签不是独立的。如果我添加一个新的“类(class)”并选择一些产品,其他类(class)中所有复选框的标签也会更改。

enter image description here

我希望我的帖子不要太乱,我不会经常在 Stack Overflow 上编辑消息

编辑结束


我有一个带有嵌套形式数组的 react 形式来描述包含多个类(class)的菜单每门类(class)都包含几种产品,但我不知道如何让它发挥作用。我的实际问题是我无法恢复我的二级控件。

这是菜单的json结构:

{
"name": "",
"description": "",
"price": "",
"courses": [
{
"courseName": "",
"products": [
{
"product": ""
}
]
}
]
}

我以这个项目为例:

Deep nested reactive form

为了便于阅读,这是我的简化形式:

    <form [formGroup]="menuForm" (ngSubmit)="onSubmit(menuForm)">

<div class="form-group">
<input
class="form-control"
formControlName="name"
type="text">
</div>
<div class="form-group">
<textarea
class="form-control"
formControlName="description"></textarea>
</div>
<div class="col-md-3 form-group">
<input
class="form-control"
formControlName="price"
type="number">
</div>
</div>
<div class="row col-md-12">
<button class="btn btn-outline-dark" type="button" (click)="onAddCourse()">
Add course
</button>
</div>

<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">
<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 // <- will load products that have course Name selected form the input 'courseName'above
</button>

<div class="row" formArrayName="products">
<div class="col-md-12"
*ngFor="let product of getProducts(menuForm); 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>

<br>
<div class="row col-md-12">
<button class="btn btn-success mr-1" type="submit" [disabled]="!menuForm.valid">{{buttonSubmitLabel}}</button>
</div>
</form>

这是我在 TS 中的表单初始化:

export class MenuEditComponent implements OnInit {

menuForm: FormGroup;
menu: MenuModel;
categories: CategoryModel[];
...

constructor(private router: Router,
private route: ActivatedRoute,
private productService: ProductService,
private menuService: MenuService) { }

ngOnInit(): void {
this.productService.getCategories().subscribe(
result => {
this.categories = result;
},
error => {
console.log(error);
this.categories = [];
});
this.initForm();
}

initForm() {
this.menuForm = new FormGroup({
name: new FormControl('', [Validators.required, Validators.maxLength(100)]),
description: new FormControl('', Validators.maxLength(255)),
price: new FormControl('', [Validators.required, Validators.min(0)]),
courses: new FormArray([
this.initCourse(),
])
});
}

initCourse() {
return new FormGroup({
courseName: new FormControl(''),
products: new FormArray([
this.initProduct()
])
});
}

initProduct() {
return new FormGroup({
product: new FormControl('')
});
}

getCourses(form) {
return form.controls.courses.controls;
}

getProducts(form) {
return form.controls.products.controls;
}

onAddCourse() {
const control = this.menuForm.get('courses') as FormArray;
control.push(this.initCourse());
}

onLoadProducts(i: number) {
console.log(this.menuForm.controls.courses);
const courseControl = this.menuForm.get('courses') as FormArray;
const course = courseControl.at(i).get('courseName').value;
console.log(course);
const products: ProductModel[] = this.mapProducts.get(course);
console.log(products);
const productControl = this.menuForm.get('courses').get[i].get('products') as FormArray;

onSubmit(menuForm: FormGroup) {
...
}

...
}

如果我这样离开后端,我会出错:

Cannot read property 'controls' of undefined at MenuEditComponent.getProducts

因此我的“产品”FormArray 未初始化。如果我这样做:

  getProducts(form) {
return form.controls.products?.controls;
}

我不再有错误,但我无法访问产品 formControls。如果我尝试:

  onLoadProducts(i: number) {
const courseControl = this.menuForm.get('courses') as FormArray;
const course = courseControl.at(i).get('courseName').value;
const products: ProductModel[] = this.mapProducts.get(course);
const productControl = this.menuForm.get('courses').get[i].get('products') as FormArray;
//On the last line i get a 'Cannot read property 'get' of undefined'
...
}

我做错了什么?为什么我的“产品”FormArray 没有初始化?

非常感谢您的帮助!

最佳答案

我查看了您的 stackblitz,并对其进行了修改并使其正常工作。您不需要将 formControlName 与您的产品绑定(bind),因为您不是从前端 UI 设置它们,而只是选择它们。我在类 ProductModel 中添加了一个名为 added 的字段,然后我刚刚为复选框实现了 change 事件以将其标记为真或假.

您还可以看到我是如何为产品设置值(value)的。当您点击 Load Products 按钮时,您将添加空的 FormGroup 但您还应该在其中设置 product 控件与产品数据。您可以在代码中看到我在 LoadProducts 方法中的操作方式

之后,您可以在产品循环中看到我是如何获得产品字段的。循环实际上给了我们 FormGroup 我们必须从中获取产品字段值

这是正在完成这项工作的堆栈 Blitz 。

https://stackblitz.com/edit/angular-ivy-ohwv1v

这部分你可以特别注意

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>

您应该将值绑定(bind)到产品的添加属性,并且名称也应该显示在产品对象的标签内。

希望这将帮助您进一步进行。

And the second problem is that the labels of my checkboxes are not independent. If i add a new 'course' and that i select some products, the labels of all checkboxes in other courses are changed too.

上述问题已解决

I don't know how to be able to retrieve something like:

而不是 productName: true/false 你有整个产品对象可用,added 字段将标记它的 checked/unchecked

关于angular - 如何在 Angular 9 Reactive Form 中获取嵌套的 FormArray 控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62257541/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com