【发布时间】:2020-09-27 03:37:47
【问题描述】:
编辑
由于上面 Chellappan 的回答,问题的第一部分得到了解决,但我遇到了其他问题,这让我做了一个堆栈闪电战,可以在这里找到: 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
}
]
第二个问题是我的复选框的标签不是独立的。如果我添加一个新的“课程”并选择了一些产品,其他课程中所有复选框的标签也会更改。
我希望我的帖子不要太乱,我不经常在 Stack Overflow 上编辑消息
编辑结束
我有一个带有嵌套表单数组的反应表单来描述一个包含几门课程的菜单 每门课程都包含几种产品,但我不知道如何使它起作用。 我的实际问题是我无法检索我的第二级控件。
这里是菜单的json结构:
{
"name": "",
"description": "",
"price": "",
"courses": [
{
"courseName": "",
"products": [
{
"product": ""
}
]
}
]
}
我以这个项目为例:
为了便于阅读,这是我的简化形式:
<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 没有初始化?
非常感谢您的帮助!
【问题讨论】:
-
您编写的代码在某些方面没有意义。为什么要将
formControlName='courseName'绑定到select列表?这意味着当您更改选项时,课程名称将在课程子表单中更新。其次,这条线let course of courses是什么意思?你添加的课程不是用top form吗?还是这里的课程来源不同?你能把你所有的代码放在 stackblitz.com 上吗?我认为这段代码存在一些逻辑问题。 -
感谢您的回答,您可能是对的,我对 Angular 还不太满意,我才刚刚开始使用它。和反应形式对我来说有点模糊。我将尝试创建一个 stackblitz,我以前从未使用过它。为了回答您的问题,我正在从 api 中检索课程列表,这些类别将填充选择输入,当我们选择其中一门课程时,它将从同一个 api 中获取该课程名称中的产品列表。我将尝试直接在 stackblitz 上创建它。感谢您的宝贵时间!
-
这里是stackblitz:stackblitz.com/edit/angular-ivy-bzh3dh我会更新我的帖子来描述我现在遇到的问题!
标签: angular typescript angular-reactive-forms formarray