typescript Angular 2/4 编辑表单填充 FormArray 控件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43670139/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 2/4 Edit Form Populate FormArray Controls
提问by ctilley79
I'm trying to implement an edit form for a model with nested attributes (FormArray). I'm having trouble with the syntax and I'm uncertain whether I'm on the right track. The attributes for the main form work, it's the nested form I'm having problems with. Here's what I have so far.
我正在尝试为具有嵌套属性 (FormArray) 的模型实现编辑表单。我的语法有问题,我不确定我是否走在正确的轨道上。主表单的属性有效,这是我遇到问题的嵌套表单。这是我到目前为止所拥有的。
Here I initiate the form group:
这里我发起表单组:
private initForm() {
this.subscription = this.expenseService.getExpense(this.id)
.subscribe(
expense => {
this.expense = expense;
this.patchForm();
}
);
this.expenseEditForm = this.fb.group({
date: '',
amount: '',
check_number: '',
debit: '',
payee_id: '',
notes: '',
expense_expense_categories_attributes:[]
});
}
Here I patch the form to set values from an object retrieved from my backend API.
在这里,我修补表单以设置从后端 API 检索到的对象的值。
private patchForm() {
this.expenseEditForm.setValue({
date: '',
amount: this.expense.amount_cents,
check_number: this.expense.check_number,
debit: this.expense.debit,
payee_id: '',
notes: this.expense.notes,
expense_expense_categories_attributes: this.fb.array([
this.setExpenseCategories(),
])
});
}
This is where I'm stuck. How do I push onto a FormArray. If I try to push, I get an error stating that push it doesn't exist on FormArray.
这就是我被困的地方。如何推送到 FormArray。如果我尝试推送,我会收到一条错误消息,指出 FormArray 上不存在推送。
private setExpenseCategories() {
for ( let expenseCategories of this.expense.expense_expense_categories){
this.fb.array.push([
this.fb.group({
expense_category_id: [expenseCategories.expense_category_id, Validators.required],
amount: [expenseCategories.amount_cents]
])
});
}
}
Just in case it's needed. Here's my html.
以防万一。这是我的 html。
<div
*ngFor="let expensecategoriesCtl of expenseEditForm.controls.expense_expense_categories_attributes.controls let i = index"
[formGroupName]="i"
style="margin-top: 10px;">
<md-card>
<md-select class="full-width-input"
placeholder="Expense Category"
id="expense_category_id"
formControlName="expense_category_id"
>
<md-option *ngFor="let expenseCategory of expenseCategories" value="{{expenseCategory.id}}">
{{expenseCategory.category}}
</md-option>
</md-select>
<md-input-container class="full-width-input">
<input
mdInput placeholder="Amount"
type="number"
formControlName="amount">
</md-input-container>
</md-card>
</div>
回答by AJT82
Some changes to DeborahK's answer, since expense.expense_expense_categories
doesn't contain a primitive types, but objects. Therefore we cannot assign the values as is, but each object needs to be wrapped in a FormGroup
, just like you have attempted.
对 DeborahK 的答案进行了一些更改,因为expense.expense_expense_categories
不包含原始类型,而是对象。因此,我们不能按原样分配值,但每个对象都需要包装在 a 中FormGroup
,就像您尝试过的那样。
Here I have a shortened version of your code:
在这里,我有您的代码的缩短版本:
Build the form:
构建表单:
ngOnInit() {
this.expenseEditForm = this.fb.group({
notes: [''],
// notice below change, we need to mark it as an formArray
expense_expense_categories_attributes: this.fb.array([])
})
Then we call patchForm
in the callback, just like you have. That function would look like this, notice, we call this.setExpenseCategories
outside:
然后我们调用patchForm
回调,就像你一样。那个函数看起来像这样,注意,我们this.setExpenseCategories
在外面调用:
patchForm() {
this.expenseEditForm.patchValue({
notes: this.expense.notes,
})
this.setExpenseCategories()
}
Then comes the biggest change from your existing code, where we first assign the FormArray
to the variable control
and then we iterate your array received from backend, create a FormGroup
for each object and push the object to each FormGroup
:
然后是现有代码的最大变化,我们首先将 分配FormArray
给变量control
,然后迭代从后端接收的数组,FormGroup
为每个对象创建一个并将对象推送到每个FormGroup
:
setExpenseCategories(){
let control = <FormArray>this.expenseEditForm.controls.expense_expense_categories_attributes;
this.expense.expense_expense_categories.forEach(x => {
control.push(this.fb.group(x));
})
}
Then to the template, this example is without Angular Material:
然后到模板,这个例子没有Angular Material:
<form [formGroup]="expenseEditForm">
<label>Notes: </label>
<input formControlName="notes" /><br>
<!-- Declare formArrayName -->
<div formArrayName="expense_expense_categories_attributes">
<!-- iterate formArray -->
<div *ngFor="let d of expenseEditForm.get('expense_expense_categories_attributes').controls; let i=index">
<!-- Use the index for each formGroup inside the formArray -->
<div [formGroupName]="i">
<label>Amount: </label>
<input formControlName="amount" />
</div>
</div>
</div>
</form>
Finally a
最后一个
Demo
演示
回答by DeborahK
If I understand your question correctly, you may need something like this:
如果我正确理解你的问题,你可能需要这样的东西:
// Update the data on the form
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 || []));
You can see the complete example here: https://github.com/DeborahK/Angular2-ReactiveFormsin the APM - Updated folder.
您可以在此处查看完整示例:https: //github.com/DeborahK/Angular2-ReactiveForms在 APM - Updated 文件夹中。