Angular FormArray patchValue error: TypeError: value.forEach is not a function - how to resolve?
Angular FormArray patchValue error: TypeError: value.forEach is not a function - how to resolve?
页面最初是作为模板驱动形式编写的,但正在转换为响应式以添加自动保存功能。
在页面组件的构造函数中,我定义了响应式表单变量:
this.form = fb.group({
reviewer: '',
position: '',
officeName: '',
rows: fb.array([]),
comments1: '',
comments2: '',
comments3: ''
});
'rows' 是与此问题相关的字段。
在 ngInit 中,通过网络 api 发出请求以检索持久化的表单数据。数据作为行数组检索,每行包含 6 个单元格的数组。第三个单元格将绑定到 FormControl,其他单元格将呈现为静态文本。
this.rows = summaryReportQuestion.map(summaryReportQuestionObj => {
return {
cells: [
summaryReportQuestionObj.questionID,
summaryReportQuestionObj.question,
(summaryReportQuestionObj.columnSign == '$' ? (summaryReportQuestionObj.columnSign + ' ' + summaryReportQuestionObj.target) : summaryReportQuestionObj.target + ' ' + summaryReportQuestionObj.columnSign),
(summaryReportQuestionObj.budget == null ? summaryReportQuestionObj.budget : (summaryReportQuestionObj.columnSign == '$' ? summaryReportQuestionObj.columnSign + ' ' + this.utilityService.formatNumberWithCommas(Math.floor(summaryReportQuestionObj.budget), false) : summaryReportQuestionObj.budget + ' ' + summaryReportQuestionObj.columnSign)),
(summaryReportQuestionObj.average == null ? summaryReportQuestionObj.average : (summaryReportQuestionObj.columnSign == '$' ? summaryReportQuestionObj.columnSign + ' ' + this.utilityService.formatNumberWithCommas(Math.floor(summaryReportQuestionObj.average), false) : summaryReportQuestionObj.average + ' ' + summaryReportQuestionObj.columnSign)),
(summaryReportQuestionObj.top20Percent == null ? summaryReportQuestionObj.top20Percent : (summaryReportQuestionObj.columnSign == '$' ? summaryReportQuestionObj.columnSign + ' ' + this.utilityService.formatNumberWithCommas(Math.floor(summaryReportQuestionObj.top20Percent), false) : summaryReportQuestionObj.top20Percent + ' ' + summaryReportQuestionObj.columnSign))
]
};
});
let faRows = new FormArray([]);
for (var i = 0, len = this.rows.length; i < len; i++) {
let row = this.rows[i].cells;
for (var j = 0, length = this.rows[i].cells.length; j < length; j++) {
let fc = new FormControl(this.rows[i].cells[j]);
faRows.push(fc);
}
}
// this.form.setValue({rows: faRows});
// this.form.setControl('rows', faRows);
在html中:
<tbody>
<tr *ngFor="let row of rows;let r = index" [attr.data-index]="r">
<ng-container>
<td *ngFor="let cell of row.cells;let i = index" [attr.data-index]="i">
<span *ngIf="i != 2">{{cell}}</span>
<!-- <input type="text" formControlName="form.rows[r]" *ngIf="i == 2"> -->
</td>
</ng-container>
</tr>
</tbody>
根据评论和回答,我已经阐明了我的意图和代码。
[谢谢@amal 和@DeborahK]
我现在只将每行中的一个数据单元格绑定到 FormControl,每行中的其他单元格显示为:
{{细胞}}
因此我需要渲染this.rows(如html)和this.form.rows的内容。
我目前在理解如何实现这一点时遇到两个问题。在打字稿中,留下最后一个循环块迭代创建行的 FormControls 的数据行,数组 faRows 恰好包含我所期望的,FormControls 的 FormArray,并且每个都检索到它正确的关联保存值。但是当试图从 this.rows 复制数据来为 form.rows 创建 FormControls 时,我无法使 setValue 或 setControl 正常工作。这可能与html页面FormControl的命名有关,这是我的第二个问题。
我不清楚如何在 html 中引用表单变量来动态创建 formControlName。这是我想象的,但它不起作用。
<input type="text" formControlName="form.rows[r]" *ngIf="i == 2">
据我所知,无法使用 FormArray 调用 .patchValue。
我的表单设置类似,其中 tags 是我的 FormArray。
this.productForm = this.fb.group({
productName: ['', [Validators.required,
Validators.minLength(3),
Validators.maxLength(50)]],
productCode: ['', Validators.required],
starRating: ['', NumberValidators.range(1, 5)],
tags: this.fb.array([]),
description: ''
});
为编辑设置数据时,我必须这样做:
this.productForm.patchValue({
productName: this.product.productName,
productCode: this.product.productCode,
starRating: this.product.starRating,
description: this.product.description
});
this.productForm.setControl('tags', this.fb.array(this.product.tags || []));
我对每个简单的 FormControl 使用 patchValue
,对 FormArray 使用 setControl
。
您可以尝试一下,看看是否能解决您的问题。
页面最初是作为模板驱动形式编写的,但正在转换为响应式以添加自动保存功能。
在页面组件的构造函数中,我定义了响应式表单变量:
this.form = fb.group({
reviewer: '',
position: '',
officeName: '',
rows: fb.array([]),
comments1: '',
comments2: '',
comments3: ''
});
'rows' 是与此问题相关的字段。
在 ngInit 中,通过网络 api 发出请求以检索持久化的表单数据。数据作为行数组检索,每行包含 6 个单元格的数组。第三个单元格将绑定到 FormControl,其他单元格将呈现为静态文本。
this.rows = summaryReportQuestion.map(summaryReportQuestionObj => {
return {
cells: [
summaryReportQuestionObj.questionID,
summaryReportQuestionObj.question,
(summaryReportQuestionObj.columnSign == '$' ? (summaryReportQuestionObj.columnSign + ' ' + summaryReportQuestionObj.target) : summaryReportQuestionObj.target + ' ' + summaryReportQuestionObj.columnSign),
(summaryReportQuestionObj.budget == null ? summaryReportQuestionObj.budget : (summaryReportQuestionObj.columnSign == '$' ? summaryReportQuestionObj.columnSign + ' ' + this.utilityService.formatNumberWithCommas(Math.floor(summaryReportQuestionObj.budget), false) : summaryReportQuestionObj.budget + ' ' + summaryReportQuestionObj.columnSign)),
(summaryReportQuestionObj.average == null ? summaryReportQuestionObj.average : (summaryReportQuestionObj.columnSign == '$' ? summaryReportQuestionObj.columnSign + ' ' + this.utilityService.formatNumberWithCommas(Math.floor(summaryReportQuestionObj.average), false) : summaryReportQuestionObj.average + ' ' + summaryReportQuestionObj.columnSign)),
(summaryReportQuestionObj.top20Percent == null ? summaryReportQuestionObj.top20Percent : (summaryReportQuestionObj.columnSign == '$' ? summaryReportQuestionObj.columnSign + ' ' + this.utilityService.formatNumberWithCommas(Math.floor(summaryReportQuestionObj.top20Percent), false) : summaryReportQuestionObj.top20Percent + ' ' + summaryReportQuestionObj.columnSign))
]
};
});
let faRows = new FormArray([]);
for (var i = 0, len = this.rows.length; i < len; i++) {
let row = this.rows[i].cells;
for (var j = 0, length = this.rows[i].cells.length; j < length; j++) {
let fc = new FormControl(this.rows[i].cells[j]);
faRows.push(fc);
}
}
// this.form.setValue({rows: faRows});
// this.form.setControl('rows', faRows);
在html中:
<tbody>
<tr *ngFor="let row of rows;let r = index" [attr.data-index]="r">
<ng-container>
<td *ngFor="let cell of row.cells;let i = index" [attr.data-index]="i">
<span *ngIf="i != 2">{{cell}}</span>
<!-- <input type="text" formControlName="form.rows[r]" *ngIf="i == 2"> -->
</td>
</ng-container>
</tr>
</tbody>
根据评论和回答,我已经阐明了我的意图和代码。 [谢谢@amal 和@DeborahK] 我现在只将每行中的一个数据单元格绑定到 FormControl,每行中的其他单元格显示为: {{细胞}}
因此我需要渲染this.rows(如html)和this.form.rows的内容。
我目前在理解如何实现这一点时遇到两个问题。在打字稿中,留下最后一个循环块迭代创建行的 FormControls 的数据行,数组 faRows 恰好包含我所期望的,FormControls 的 FormArray,并且每个都检索到它正确的关联保存值。但是当试图从 this.rows 复制数据来为 form.rows 创建 FormControls 时,我无法使 setValue 或 setControl 正常工作。这可能与html页面FormControl的命名有关,这是我的第二个问题。
我不清楚如何在 html 中引用表单变量来动态创建 formControlName。这是我想象的,但它不起作用。
<input type="text" formControlName="form.rows[r]" *ngIf="i == 2">
据我所知,无法使用 FormArray 调用 .patchValue。
我的表单设置类似,其中 tags 是我的 FormArray。
this.productForm = this.fb.group({
productName: ['', [Validators.required,
Validators.minLength(3),
Validators.maxLength(50)]],
productCode: ['', Validators.required],
starRating: ['', NumberValidators.range(1, 5)],
tags: this.fb.array([]),
description: ''
});
为编辑设置数据时,我必须这样做:
this.productForm.patchValue({
productName: this.product.productName,
productCode: this.product.productCode,
starRating: this.product.starRating,
description: this.product.description
});
this.productForm.setControl('tags', this.fb.array(this.product.tags || []));
我对每个简单的 FormControl 使用 patchValue
,对 FormArray 使用 setControl
。
您可以尝试一下,看看是否能解决您的问题。