Angular - 如何跟踪 FormGroup 中的数组数组
Angular - How to keep track of array of arrays in a FormGroup
我正在尝试创建一个包含 select 控件列表的表单(只是为了简单起见)。
我不打算向表单添加新的 select,我只想跟踪每个 select 控件中的 selected 选项。
这是我用来生成 select 控件的 json:
sports = [
{
sportId: '1',
desc: 'Football',
categories: [
{
categId: '1',
desc: 'U-18'
},
{
categId: '1',
desc: 'U-20'
},
{
categId: '2',
desc: 'U-23'
}
]
},
{
sportId: '2',
desc: 'Volleyball',
categories: [
{
categId: '3',
desc: 'Junior'
},
{
categId: '4',
desc: 'Youth'
}
]
},
{
sportId: '3',
desc: 'Tennis',
categories: [
{
categId: '5',
desc: 'Singles'
},
{
categId: '6',
desc: 'Doubles'
}
]
}
];
这是我的表格html
<form [formGroup]="registrationForm"(submit)="save()">
<div class="form-group">
<label for="firstname">First Name</label>
<input
type="text"
class="form-control"
id="firstname"
formControlName="firstName"
placeholder="First Name"
/>
</div>
<div class="form-group">
<label for="lastname">Last Name</label>
<input
type="text"
class="form-control"
formControlName="lastName"
id="lastname"
placeholder="Last Name"
/>
</div>
<div class="form-group" *ngFor="let sport of sports; let i = index">
<label attr.for="sport_{{i}}">{{sport.desc}}</label>
<select class="form-control" id="sport_{{i}}">
<option value="0">Select one</option>
<option *ngFor="let cat of sport.categories" [value]="cat.categId">{{cat.desc}}</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
为 firstName 和 lastName 构建表单很简单:
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.registrationForm = this.fb.group({
firstName: '',
lastName: ''
});
}
但我不确定如何跟踪每个不同 select 控件上的 selected 选项。
如果你能在这里帮助我,我将不胜感激。
编辑
这是一个演示
您可能使用了错误的结构来生成动态表单控件。
您需要说明您使用的是什么动态控件,如下所示:
profileForm = this.fb.group({
firstName: ['', Validators.required],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: ['']
}),
aliases: this.fb.array([
this.fb.control('') // this states that, there will be dynamic form control array
])
});
然后在读取控件的值后,您可以像下面这样使用;
this.profileForm.get('aliases') as FormArray
您可以在此处从办公网站编辑demo。
如果你能提供stackblitz来检查问题,这对那些想回答并直接提供代码更改的人会有帮助。
您要跟踪的每个控件都可以在表单组中有一个条目:
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.registrationForm = this.fb.group({
firstName: '',
lastName: '',
// <- Each additional control should be listed here
football: '',
volleyball: '',
tennis: ''
});
}
将表单组视为您要跟踪的一组数据。因此,如果您说您对动态添加运动不感兴趣,只是跟踪它们的值,那么它们的每个值都会成为表单组中的一个条目。
您可以在此处找到 "brute force" 样式的解决方案:https://stackblitz.com/edit/angular-i7ntj3
如果您想动态添加控件(即使您不打算添加更多),您可以使用示例中所示的 FormArray。看起来您主要缺少 [formControlName]
属性 和填充 FormArray 的代码。
组件
registrationForm: FormGroup;
get categoryOptions(): FormArray {
return <FormArray>this.registrationForm.get('options');
}
constructor(private fb: FormBuilder) { }
ngOnInit(): void {
this.registrationForm = this.fb.group({
firstName: '',
lastName: '',
options: this.fb.array([])
});
// Add the sports to the FormArray
this.sports.forEach(s =>
this.categoryOptions.push(new FormControl()));
}
save() {
console.log(JSON.stringify(this.registrationForm.value));
}
注意:FormGroup 需要包含您要跟踪的所有表单控件。在上面的示例中,我们跟踪两个文本字段和一个 FormArray。 FormArray 包含一组表单控件或一组表单组。由于这些表单数组元素是 而不是 动态添加的,因此我们需要手动创建它们。这就是上面代码中 forEach
的目的。
模板
<div formArrayName="options">
<div *ngFor="let sport of sports; let i=index">
<label attr.for="i">{{sport.desc}}</label>
<select class="form-control" id="i" [formControlName]="i">
<option value="0">Select one</option>
<option *ngFor="let cat of sport.categories" [value]="cat.categId">{{cat.desc}}
</option>
</select>
</div>
</div>
注意:必须将 formArrayName 设置为 FormGroup 中定义的 FormArray 的名称。 ngFor 循环遍历每项运动并设置一个索引,该索引将映射到数组的每个元素。然后将每个 select 元素的 formControlName
设置为数组索引。
您可以在此处找到此 FormArray 解决方案:https://stackblitz.com/edit/angular-reactive-select-deborahk
希望这对您有所帮助。
把你的 ngOnInit() 改成这个。
ngOnInit(): void {
this.registrationForm = this.fb.group({
firstName: '0',
lastName: '0',
sportsFormArray: this.fb.array([])
});
this.sports.forEach((s) => {
this.sportsFormArray.push(this.fb.control(0));
});
}
而在html中,控制代码的数组将是这样的
<div formArrayName="sportsFormArray">
<div *ngFor="let sport of sports; let i=index">
<label>{{sport.desc}}</label>
<select class="form-control" id="sport_{{i}}" [formControlName]="i">
<option value="0">Select one</option>
<option *ngFor="let cat of sport.categories" [value]="cat.categId">{{cat.desc}}</option>
</select>
</div>
</div>
我正在尝试创建一个包含 select 控件列表的表单(只是为了简单起见)。
我不打算向表单添加新的 select,我只想跟踪每个 select 控件中的 selected 选项。
sports = [
{
sportId: '1',
desc: 'Football',
categories: [
{
categId: '1',
desc: 'U-18'
},
{
categId: '1',
desc: 'U-20'
},
{
categId: '2',
desc: 'U-23'
}
]
},
{
sportId: '2',
desc: 'Volleyball',
categories: [
{
categId: '3',
desc: 'Junior'
},
{
categId: '4',
desc: 'Youth'
}
]
},
{
sportId: '3',
desc: 'Tennis',
categories: [
{
categId: '5',
desc: 'Singles'
},
{
categId: '6',
desc: 'Doubles'
}
]
}
];
这是我的表格html
<form [formGroup]="registrationForm"(submit)="save()">
<div class="form-group">
<label for="firstname">First Name</label>
<input
type="text"
class="form-control"
id="firstname"
formControlName="firstName"
placeholder="First Name"
/>
</div>
<div class="form-group">
<label for="lastname">Last Name</label>
<input
type="text"
class="form-control"
formControlName="lastName"
id="lastname"
placeholder="Last Name"
/>
</div>
<div class="form-group" *ngFor="let sport of sports; let i = index">
<label attr.for="sport_{{i}}">{{sport.desc}}</label>
<select class="form-control" id="sport_{{i}}">
<option value="0">Select one</option>
<option *ngFor="let cat of sport.categories" [value]="cat.categId">{{cat.desc}}</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
为 firstName 和 lastName 构建表单很简单:
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.registrationForm = this.fb.group({
firstName: '',
lastName: ''
});
}
但我不确定如何跟踪每个不同 select 控件上的 selected 选项。
如果你能在这里帮助我,我将不胜感激。
编辑
这是一个演示
您可能使用了错误的结构来生成动态表单控件。 您需要说明您使用的是什么动态控件,如下所示:
profileForm = this.fb.group({
firstName: ['', Validators.required],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: ['']
}),
aliases: this.fb.array([
this.fb.control('') // this states that, there will be dynamic form control array
])
});
然后在读取控件的值后,您可以像下面这样使用;
this.profileForm.get('aliases') as FormArray
您可以在此处从办公网站编辑demo。
如果你能提供stackblitz来检查问题,这对那些想回答并直接提供代码更改的人会有帮助。
您要跟踪的每个控件都可以在表单组中有一个条目:
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.registrationForm = this.fb.group({
firstName: '',
lastName: '',
// <- Each additional control should be listed here
football: '',
volleyball: '',
tennis: ''
});
}
将表单组视为您要跟踪的一组数据。因此,如果您说您对动态添加运动不感兴趣,只是跟踪它们的值,那么它们的每个值都会成为表单组中的一个条目。
您可以在此处找到 "brute force" 样式的解决方案:https://stackblitz.com/edit/angular-i7ntj3
如果您想动态添加控件(即使您不打算添加更多),您可以使用示例中所示的 FormArray。看起来您主要缺少 [formControlName]
属性 和填充 FormArray 的代码。
组件
registrationForm: FormGroup;
get categoryOptions(): FormArray {
return <FormArray>this.registrationForm.get('options');
}
constructor(private fb: FormBuilder) { }
ngOnInit(): void {
this.registrationForm = this.fb.group({
firstName: '',
lastName: '',
options: this.fb.array([])
});
// Add the sports to the FormArray
this.sports.forEach(s =>
this.categoryOptions.push(new FormControl()));
}
save() {
console.log(JSON.stringify(this.registrationForm.value));
}
注意:FormGroup 需要包含您要跟踪的所有表单控件。在上面的示例中,我们跟踪两个文本字段和一个 FormArray。 FormArray 包含一组表单控件或一组表单组。由于这些表单数组元素是 而不是 动态添加的,因此我们需要手动创建它们。这就是上面代码中 forEach
的目的。
模板
<div formArrayName="options">
<div *ngFor="let sport of sports; let i=index">
<label attr.for="i">{{sport.desc}}</label>
<select class="form-control" id="i" [formControlName]="i">
<option value="0">Select one</option>
<option *ngFor="let cat of sport.categories" [value]="cat.categId">{{cat.desc}}
</option>
</select>
</div>
</div>
注意:必须将 formArrayName 设置为 FormGroup 中定义的 FormArray 的名称。 ngFor 循环遍历每项运动并设置一个索引,该索引将映射到数组的每个元素。然后将每个 select 元素的 formControlName
设置为数组索引。
您可以在此处找到此 FormArray 解决方案:https://stackblitz.com/edit/angular-reactive-select-deborahk
希望这对您有所帮助。
把你的 ngOnInit() 改成这个。
ngOnInit(): void {
this.registrationForm = this.fb.group({
firstName: '0',
lastName: '0',
sportsFormArray: this.fb.array([])
});
this.sports.forEach((s) => {
this.sportsFormArray.push(this.fb.control(0));
});
}
而在html中,控制代码的数组将是这样的
<div formArrayName="sportsFormArray">
<div *ngFor="let sport of sports; let i=index">
<label>{{sport.desc}}</label>
<select class="form-control" id="sport_{{i}}" [formControlName]="i">
<option value="0">Select one</option>
<option *ngFor="let cat of sport.categories" [value]="cat.categId">{{cat.desc}}</option>
</select>
</div>
</div>