Angular2:在 FormArray 的索引 1 处找不到表单控件
Angular2: Cannot find form control at index 1 at FormArray
在运行时,我从 JSON 对象获取所有记录,在表单控件中我获取值。但是,在表单数组中,我只得到许多记录中的第一个。
控制台显示的错误:
Cannot find form control at index 1 at FormArray._throwIfControlMissing
JSON 对象和错误的图像:
- 界面
export interface IService {
ServiceID: number,
Name: string,
Staffs: IStaffView[]
}
export interface IStaffView {
StaffServiceID: number,
StaffID: number,
Name: string
}
- 组件
import { Component, OnInit, Input } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Location } from '@angular/common';
import { Observable } from 'rxjs/Rx';
import { FormBuilder, FormGroup, FormControl, FormArray , Validators } from '@angular/forms';
import { RESTService } from '../../Service/REST.service';
import { IService, IStaffView } from '../../Model/service.model';
import { DBOperation } from '../../Shared/enum';
import { Global } from '../../Shared/global';
@Component({
selector: 'app-service-detail',
templateUrl: 'app/Components/service-detail/service-detail.component.html'
})
export class ServiceDetailComponent implements OnInit {
service: IService;
services: IService[];
staffview: IStaffView;
staffsview: IStaffView[];
serviceFrm: FormGroup;
Staffs: FormArray;
msg: string;
indLoading: boolean = false;
btnTitle: string;
dbops: DBOperation;
constructor(
private fb: FormBuilder,
private _restService: RESTService,
private location: Location,
private _route: ActivatedRoute
) {
const id = this._route.snapshot.params['id'];
if (!id || id == 0) {
this.btnTitle = 'Save';
this.dbops = DBOperation.create;
} else {
this.btnTitle = 'Edit';
this.dbops = DBOperation.update
}
}
ngOnInit(): void {
//this.Staffs = this.fb.array([
// this.initStaff()
//]);
this.serviceFrm = this.fb.group({
ServiceID: [''],
Name: ['', Validators.required],
Staffs: this.fb.array([
this.initStaff()
])
});
this.getService();
}
initStaff() {
return this.fb.group({
StaffServiceID: [''],
StaffID: [''],
Name: ['']
});
}
getService(): void {
const id = parseInt(this._route.snapshot.params['id']);
if (id && id > 0) {
this.indLoading = true;
this._restService.getById('/api/serviceapi/', id)
.subscribe(resp => this.serviceFrm.setValue(resp)
, error => this.msg = <any>error);
}
}
}
- HTML代码
<div class="row form-group">
<div class="col-md-3">
<label for="message-text" class="control-label">Staffs</label>
</div>
<div formArrayName="Staffs">
<div *ngFor="let staff of serviceFrm.controls.Staffs.controls; let i=index" formGroupName="{{i}}">
<div>
<label>Name</label>
<input type="text" class="form-control" formControlName="Name">
</div>
</div>
</div>
</div>
试试这个:
<div class="row form-group">
<div class="col-md-3">
<label for="message-text" class="control-label">Staffs</label>
</div>
<div >
<div *ngFor="let staff of serviceFrm.controls.Staffs.controls; let i=index" formArrayName="Staffs">
<div [formGroupName]="i">
<label>Name</label>
<input type="text" class="form-control" formControlName="Name">
</div>
</div>
</div>
</div>
上述错误是由于调用this.serviceFrm.setValue(resp)
(https://github.com/angular/angular/blob/master/packages/forms/src/model.ts#L1382)造成的。
This method performs strict checks, so it will throw an error if you try
to set the value of a control that doesn't exist or if you exclude the
value of a control.
您正在尝试将一个包含 3 个项目的数组(根据您的快照)分配给 FormArray,在索引 0 处只有一个初始 FormGroup,因此在索引 1 处分配值失败,因为它不存在。
要解决这个问题,请在修补值之前清空表单数组,使用 patchValue()
(接受部分值)而不是 setValue()
,然后循环推送每个值:
getService(): void {
const id = parseInt(this._route.snapshot.params['id']);
if (id && id > 0) {
this.indLoading = true;
this._restService.getById('/api/serviceapi/', id).subscribe(
resp => {
// get form array reference
const staffs = this.serviceFrm.get('Staffs') as FormArray;
// empty form array
while (staffs.length) {
staffs.removeAt(0);
}
// use patchValue instead of setValue
this.serviceFrm.patchValue(resp);
// add form array values in a loop
resp.Staffs.forEach(staff => staffs.push(this.fb.group(staff));
},
error => this.msg = <any>error
);
}
}
可以将 setControl
与 FormArrays 一起使用。下面的代码是来自 Deborah Kurata:
的示例
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: ''
});
...
// 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 line makes the array update!
this.productForm.setControl('tags', this.fb.array(this.product.tags || []));
在运行时,我从 JSON 对象获取所有记录,在表单控件中我获取值。但是,在表单数组中,我只得到许多记录中的第一个。
控制台显示的错误:
Cannot find form control at index 1 at FormArray._throwIfControlMissing
JSON 对象和错误的图像:
- 界面
export interface IService {
ServiceID: number,
Name: string,
Staffs: IStaffView[]
}
export interface IStaffView {
StaffServiceID: number,
StaffID: number,
Name: string
}
- 组件
import { Component, OnInit, Input } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Location } from '@angular/common';
import { Observable } from 'rxjs/Rx';
import { FormBuilder, FormGroup, FormControl, FormArray , Validators } from '@angular/forms';
import { RESTService } from '../../Service/REST.service';
import { IService, IStaffView } from '../../Model/service.model';
import { DBOperation } from '../../Shared/enum';
import { Global } from '../../Shared/global';
@Component({
selector: 'app-service-detail',
templateUrl: 'app/Components/service-detail/service-detail.component.html'
})
export class ServiceDetailComponent implements OnInit {
service: IService;
services: IService[];
staffview: IStaffView;
staffsview: IStaffView[];
serviceFrm: FormGroup;
Staffs: FormArray;
msg: string;
indLoading: boolean = false;
btnTitle: string;
dbops: DBOperation;
constructor(
private fb: FormBuilder,
private _restService: RESTService,
private location: Location,
private _route: ActivatedRoute
) {
const id = this._route.snapshot.params['id'];
if (!id || id == 0) {
this.btnTitle = 'Save';
this.dbops = DBOperation.create;
} else {
this.btnTitle = 'Edit';
this.dbops = DBOperation.update
}
}
ngOnInit(): void {
//this.Staffs = this.fb.array([
// this.initStaff()
//]);
this.serviceFrm = this.fb.group({
ServiceID: [''],
Name: ['', Validators.required],
Staffs: this.fb.array([
this.initStaff()
])
});
this.getService();
}
initStaff() {
return this.fb.group({
StaffServiceID: [''],
StaffID: [''],
Name: ['']
});
}
getService(): void {
const id = parseInt(this._route.snapshot.params['id']);
if (id && id > 0) {
this.indLoading = true;
this._restService.getById('/api/serviceapi/', id)
.subscribe(resp => this.serviceFrm.setValue(resp)
, error => this.msg = <any>error);
}
}
}
- HTML代码
<div class="row form-group">
<div class="col-md-3">
<label for="message-text" class="control-label">Staffs</label>
</div>
<div formArrayName="Staffs">
<div *ngFor="let staff of serviceFrm.controls.Staffs.controls; let i=index" formGroupName="{{i}}">
<div>
<label>Name</label>
<input type="text" class="form-control" formControlName="Name">
</div>
</div>
</div>
</div>
试试这个:
<div class="row form-group">
<div class="col-md-3">
<label for="message-text" class="control-label">Staffs</label>
</div>
<div >
<div *ngFor="let staff of serviceFrm.controls.Staffs.controls; let i=index" formArrayName="Staffs">
<div [formGroupName]="i">
<label>Name</label>
<input type="text" class="form-control" formControlName="Name">
</div>
</div>
</div>
</div>
上述错误是由于调用this.serviceFrm.setValue(resp)
(https://github.com/angular/angular/blob/master/packages/forms/src/model.ts#L1382)造成的。
This method performs strict checks, so it will throw an error if you try to set the value of a control that doesn't exist or if you exclude the value of a control.
您正在尝试将一个包含 3 个项目的数组(根据您的快照)分配给 FormArray,在索引 0 处只有一个初始 FormGroup,因此在索引 1 处分配值失败,因为它不存在。
要解决这个问题,请在修补值之前清空表单数组,使用 patchValue()
(接受部分值)而不是 setValue()
,然后循环推送每个值:
getService(): void {
const id = parseInt(this._route.snapshot.params['id']);
if (id && id > 0) {
this.indLoading = true;
this._restService.getById('/api/serviceapi/', id).subscribe(
resp => {
// get form array reference
const staffs = this.serviceFrm.get('Staffs') as FormArray;
// empty form array
while (staffs.length) {
staffs.removeAt(0);
}
// use patchValue instead of setValue
this.serviceFrm.patchValue(resp);
// add form array values in a loop
resp.Staffs.forEach(staff => staffs.push(this.fb.group(staff));
},
error => this.msg = <any>error
);
}
}
可以将 setControl
与 FormArrays 一起使用。下面的代码是来自 Deborah Kurata:
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: ''
});
...
// 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 line makes the array update!
this.productForm.setControl('tags', this.fb.array(this.product.tags || []));