我有一个包含字符串数组的表单,每次我向列表中添加一个元素时,问题是当我使用setValue设置数组中的值时,它会显示以下错误
<button (click)="addNewCompany()">Add new Company</button><br><br>
<form [formGroup]="myForm">
<div formArrayName="companies">
<div *ngFor="let comp of getForm(); let i=index>
<fieldset>
<legend>
<h3>COMPANY {{i+1}}: </h3>
</legend>
<label>Company Name: </label>
<input [formControlName]="i" /><span><button (click)="deleteCompany(i)">Delete Company</button></span>
</fieldset>
</div>
</div><br>
</form>
export class AppComponent implements OnInit {
@Input()
public product: Product;
myForm: FormGroup;
constructor(private fb: FormBuilder) {
this.myForm = this.fb.group({
companies: this.fb.array([])
});
}
ngOnInit() {
this.addNewCompany();
this.myForm.controls['companies'].setValue(this.product.companies); // error
}
getForm(): any {
return this.myForm.get("companies")["controls"];
}
addNewCompany() {
const control = <FormArray>this.myForm.get("companies");
control.push(this.fb.control(''));
}
deleteCompany(index) {
let control = <FormArray>this.myForm.controls.companies;
control.removeAt(index);
}
}
错误错误:没有向该数组注册任何表单控件 然而。如果您使用的是ngModel,则可能要检查下一个勾号(例如 使用setTimeout)。
答案 0 :(得分:0)
如果您尝试从控件设置companies
,则该值必须是一个数组,并确保添加新的表单控件作为数组值的基础
product = {
companies:['company 01' , 'company 02']
}
ngOnInit() {
// make sure you have set a default value to product like {companies:[]}
for (let p of this.product.companies) {
this.addNewCompany();
}
this.myForm.controls['companies'].setValue(this.product.companies);
}
如果使用 setValue 方法,则必须提供控件长度的值基,否则,如果数组控件长度小于或等于数组值,则数组长度必须与控件长度相同控制长度。
patchValue 没有关于控件长度的约束,但这意味着如果您将公司设置为10,而您只有一个控件,则您只会获得第一家公司,另一个将消失,因此在这种情况下,请确保使用setValue或patchValue,但请确保控件的长度与值
相同
答案 1 :(得分:0)
您可以移动在form
内创建ngOnInit
的逻辑。像这样:
@Input()
public product: Product;
myForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.myForm = this.fb.group({
companies: this.fb.array(this.product ? this.product.companies.map(company => new FormControl(company)) : [])
});
}
addNewCompany() {
this.companies.push(new FormControl());
}
deleteCompany(i) {
this.companies.removeAt(i);
}
get companies() {
return ( < FormArray > this.myForm.get('companies'));
}
但是可能无法保证product
@Input
属性将在时间之前设置。
因此,为了确保在使用form
companies
创建FormArray
之前已对其进行了设置,您可能需要在其中初始化product
属性通过服务代替。
您必须创建一个DataService
来为您完成:
import { Injectable } from '@angular/core';
import { Product } from './product.model';
@Injectable()
export class DataService {
product: Product;
constructor() { }
setProduct(product) {
this.product = product;
}
}
然后可以将其注入到父组件中以设置product
,并注入到子组件中以通过ngOnInit
生命周期挂钩方法获得产品。像这样:
myForm: FormGroup;
constructor(
private fb: FormBuilder,
private dataService: DataService
) {}
ngOnInit() {
this.myForm = this.fb.group({
companies: this.fb.array(this.dataService.product ? this.dataService.product.companies.map(company => new FormControl(company)) : [])
});
}
addNewCompany() {
this.companies.push(new FormControl());
}
deleteCompany(i) {
this.companies.removeAt(i);
}
get companies() {
return ( < FormArray > this.myForm.get('companies'));
}
这是您推荐的Working Sample Demo。