响应式表单的输入数组
Array of input on Reactive Forms
我正在努力完成这样的事情
我有一份要订阅的计划列表
{ id: 1, data: '1GB', minsms: '5.000', value: 7.5, simCards: 1 },
{ id: 2, data: '3GB', minsms: '5.000', value: 10, simCards: 3 },
{ id: 3, data: '10GB', minsms: '5.000', value: 15, simCards: 2 },
{ id: 4, data: '20GB', minsms: '5.000', value: 20, simCards: 1 },
客户可以选择每个计划有多少张 SIM 卡,我想进行验证(即使是零卡,客户也需要 select)
我尝试使用 FormArray,但卡住了。有人可以帮助我吗?
代码(为了题我重新写了一个)
https://stackblitz.com/edit/angular-ivy-mwvat5
谢谢
已编辑
在 Eliseo 的帮助和指导下,我使用 FormArray 和 FormControl 在 stackblitz 上重写了代码
您有一系列计划,并且想要管理一系列“simCards”。由于您只需要 一个 输入,因此您需要一个 FormControls 的 FormArray。
看到你只需要一个数组(**),所以你可以简单定义
simCards:FormArray
您可以在 .ts 中订阅 (*) 以创建 FormArray
plans:any[]
ngOnInit()
{
this._plansService.getPlans().subscribe(res=>{
this.plans=res;
this.simCards=new FormArray(res.map(_=>new FormControl(0)))
})
}
并创建一个函数来获取 formArray 的控件
getControl(index)
{
return this.simCards.at(index) as FormControl
}
而你使用
<!--see that iterate over simCards.controls-->
<mat-form-field *ngFor="let control of simCards.controls;let i=index">
<mat-label
>Num of SIM cards for {{ plans[i].data }} / {{ plans[i].minsms }} at
{{ plans[i].value | currency: 'EUR' }}</mat-label
>
<input matInput type="text" [formControl]="getControl(i)" />
</mat-form-field>
注意,simCars 的值只是一个“数字”数组(实际上是字符串),因此,在提交时您需要做一些类似的事情
submit()
{
const values=this.plans.map((x:any,index:number)=>{
id:x.id,
simsCards:this.simCards.value[index]
})
this._plansService.save(values)
}
(*)别忘了取消订阅!
您还可以选择创建具有两个属性的 FormGroups 的 formArray:id 和 simsCards。在这种情况下,您可以使用
ngOnInit()
{
this._plansService.getPlans().subscribe(res=>{
this.plans=res;
this.simCards=new FormArray(res.map((x:any)=>new FormGroup({
id:new FormControl(x.id),
simCards:new FormControl(0)
})
))
})
}
你创建函数getGroup
getGroup(index)
{
return this.simCards.at(index) as FormGroup
}
并使用
<mat-form-field *ngFor="let control of simCards.controls;let i=index" [formGroup]="getGroup(i)">
<mat-label
>Num of SIM cards for {{ plans[i].data }} / {{ plans[i].minsms }} at
{{ plans[i].value | currency: 'EUR' }}</mat-label
>
<input matInput type="text" formControlName="simCards" />
</mat-form-field>
看到了,在这种情况下 this.simCards.value 给我们一个包含 id 和 simCards 的对象数组
最后,如果我们想使用管道异步而不是订阅,我们可以使用“tap”来创建 formArray
ngOnInit(){
this.plans$ = this._plansService.getPlans().pipe(
tap((plan: Plan[]) => {
this.simCards = new FormArray(
plan.map(
(x: any) =>
new FormGroup({
id: new FormControl(x.id),
simCards: new FormControl(0),
})
)
);
})
);
}
.html和上面的很像
<mat-form-field *ngFor="let plan of plans$ | async;let i=index" [formGroup]="getGroup(i)">
<mat-label
>Num of SIM cards for {{ plan.data }} / {{ plan.minsms }} at
{{ plan.value | currency: 'EUR' }}</mat-label
>
<input matInput type="text" formControlName="simCards" />
</mat-form-field>
注意:你也可以在
中定义一个里面有一个formArray的FormGroup
form=new FormGroup({
simCards:new FormArray([])
})
而且,一如既往,我们使用 FormArray 使用 getter
get simCards()
{
return this.form.get('simCards') as FormArray
}
这让我们可以避免使用函数 getGroup() 和 getControl() 将 mat-forms 封装在一个表单中
如果 FormControls 的 FormArray
<form [formGroup]="form">
<div formArrayName="simCards">
<mat-form-field
*ngFor="let plan of plans; let i = index"
>
<mat-label>...</mat-label
>
<input matInput type="text" [formControlName]="i" />
</mat-form-field>
</div>
</form>
ngOnInit()
{
this._plansService.getPlans().subscribe(res=>{
this.plans=res;
this.form=new FormGroup({
simCards:new FormArray(res.map(_=>new FormControl(0)))
})
})
}
如果 FormGroups 的 FormArray
<form [formGroup]="form">
<div formArrayName="simCards">
<mat-form-field *ngFor="let control of simCards.controls;let i=index"
[formGroupName]="i" >
<label>...</label>
<input matInput formControlName="simCards" type="text" />
</mat-form-field>
</div>
</form>
ngOnInit()
{
this._plansService.getPlans().subscribe(res=>{
this.plans=res;
this.form=new FormGroup({
simCards:new FormArray(res.map((x:any)=>new FormGroup({
id:new FormControl(x.id),
simCards:new FormControl(0)
})
))
})
})
}
如果使用管道异步,我们需要将上面的表格包含在 *ngIf 中
<div *ngIf="{ plan: plans$ | async } as data">
<form [formGroup]="form">
<div formArrayName="simCards">
<mat-form-field
*ngFor="let control of simCards.controls; let i = index"
[formGroupName]="i"
>
<mat-label
>Num of SIM cards for {{ data.plan[i].data }} /
{{ data.plan[i].minsms }} at
{{ data.plan[i].value | currency: 'EUR' }}</mat-label
>
<input matInput type="text" formControlName="simCards" />
</mat-form-field>
</div>
</form>
</div>
this.plans$ = this._plansService.getPlans().pipe(
tap((plan: Plan[]) => {
this.form=new FormGroup({
simCards: new FormArray(
plan.map(
(x: any) =>
new FormGroup({
id: new FormControl(x.id),
simCards: new FormControl(0),
})
)
)
})
})
);
我正在努力完成这样的事情
我有一份要订阅的计划列表
{ id: 1, data: '1GB', minsms: '5.000', value: 7.5, simCards: 1 },
{ id: 2, data: '3GB', minsms: '5.000', value: 10, simCards: 3 },
{ id: 3, data: '10GB', minsms: '5.000', value: 15, simCards: 2 },
{ id: 4, data: '20GB', minsms: '5.000', value: 20, simCards: 1 },
客户可以选择每个计划有多少张 SIM 卡,我想进行验证(即使是零卡,客户也需要 select)
我尝试使用 FormArray,但卡住了。有人可以帮助我吗?
代码(为了题我重新写了一个) https://stackblitz.com/edit/angular-ivy-mwvat5
谢谢
已编辑
在 Eliseo 的帮助和指导下,我使用 FormArray 和 FormControl 在 stackblitz 上重写了代码
您有一系列计划,并且想要管理一系列“simCards”。由于您只需要 一个 输入,因此您需要一个 FormControls 的 FormArray。
看到你只需要一个数组(**),所以你可以简单定义
simCards:FormArray
您可以在 .ts 中订阅 (*) 以创建 FormArray
plans:any[]
ngOnInit()
{
this._plansService.getPlans().subscribe(res=>{
this.plans=res;
this.simCards=new FormArray(res.map(_=>new FormControl(0)))
})
}
并创建一个函数来获取 formArray 的控件
getControl(index)
{
return this.simCards.at(index) as FormControl
}
而你使用
<!--see that iterate over simCards.controls-->
<mat-form-field *ngFor="let control of simCards.controls;let i=index">
<mat-label
>Num of SIM cards for {{ plans[i].data }} / {{ plans[i].minsms }} at
{{ plans[i].value | currency: 'EUR' }}</mat-label
>
<input matInput type="text" [formControl]="getControl(i)" />
</mat-form-field>
注意,simCars 的值只是一个“数字”数组(实际上是字符串),因此,在提交时您需要做一些类似的事情
submit()
{
const values=this.plans.map((x:any,index:number)=>{
id:x.id,
simsCards:this.simCards.value[index]
})
this._plansService.save(values)
}
(*)别忘了取消订阅!
您还可以选择创建具有两个属性的 FormGroups 的 formArray:id 和 simsCards。在这种情况下,您可以使用
ngOnInit()
{
this._plansService.getPlans().subscribe(res=>{
this.plans=res;
this.simCards=new FormArray(res.map((x:any)=>new FormGroup({
id:new FormControl(x.id),
simCards:new FormControl(0)
})
))
})
}
你创建函数getGroup
getGroup(index)
{
return this.simCards.at(index) as FormGroup
}
并使用
<mat-form-field *ngFor="let control of simCards.controls;let i=index" [formGroup]="getGroup(i)">
<mat-label
>Num of SIM cards for {{ plans[i].data }} / {{ plans[i].minsms }} at
{{ plans[i].value | currency: 'EUR' }}</mat-label
>
<input matInput type="text" formControlName="simCards" />
</mat-form-field>
看到了,在这种情况下 this.simCards.value 给我们一个包含 id 和 simCards 的对象数组
最后,如果我们想使用管道异步而不是订阅,我们可以使用“tap”来创建 formArray
ngOnInit(){
this.plans$ = this._plansService.getPlans().pipe(
tap((plan: Plan[]) => {
this.simCards = new FormArray(
plan.map(
(x: any) =>
new FormGroup({
id: new FormControl(x.id),
simCards: new FormControl(0),
})
)
);
})
);
}
.html和上面的很像
<mat-form-field *ngFor="let plan of plans$ | async;let i=index" [formGroup]="getGroup(i)">
<mat-label
>Num of SIM cards for {{ plan.data }} / {{ plan.minsms }} at
{{ plan.value | currency: 'EUR' }}</mat-label
>
<input matInput type="text" formControlName="simCards" />
</mat-form-field>
注意:你也可以在
中定义一个里面有一个formArray的FormGroupform=new FormGroup({
simCards:new FormArray([])
})
而且,一如既往,我们使用 FormArray 使用 getter
get simCards()
{
return this.form.get('simCards') as FormArray
}
这让我们可以避免使用函数 getGroup() 和 getControl() 将 mat-forms 封装在一个表单中
如果 FormControls 的 FormArray
<form [formGroup]="form">
<div formArrayName="simCards">
<mat-form-field
*ngFor="let plan of plans; let i = index"
>
<mat-label>...</mat-label
>
<input matInput type="text" [formControlName]="i" />
</mat-form-field>
</div>
</form>
ngOnInit()
{
this._plansService.getPlans().subscribe(res=>{
this.plans=res;
this.form=new FormGroup({
simCards:new FormArray(res.map(_=>new FormControl(0)))
})
})
}
如果 FormGroups 的 FormArray
<form [formGroup]="form">
<div formArrayName="simCards">
<mat-form-field *ngFor="let control of simCards.controls;let i=index"
[formGroupName]="i" >
<label>...</label>
<input matInput formControlName="simCards" type="text" />
</mat-form-field>
</div>
</form>
ngOnInit()
{
this._plansService.getPlans().subscribe(res=>{
this.plans=res;
this.form=new FormGroup({
simCards:new FormArray(res.map((x:any)=>new FormGroup({
id:new FormControl(x.id),
simCards:new FormControl(0)
})
))
})
})
}
如果使用管道异步,我们需要将上面的表格包含在 *ngIf 中
<div *ngIf="{ plan: plans$ | async } as data">
<form [formGroup]="form">
<div formArrayName="simCards">
<mat-form-field
*ngFor="let control of simCards.controls; let i = index"
[formGroupName]="i"
>
<mat-label
>Num of SIM cards for {{ data.plan[i].data }} /
{{ data.plan[i].minsms }} at
{{ data.plan[i].value | currency: 'EUR' }}</mat-label
>
<input matInput type="text" formControlName="simCards" />
</mat-form-field>
</div>
</form>
</div>
this.plans$ = this._plansService.getPlans().pipe(
tap((plan: Plan[]) => {
this.form=new FormGroup({
simCards: new FormArray(
plan.map(
(x: any) =>
new FormGroup({
id: new FormControl(x.id),
simCards: new FormControl(0),
})
)
)
})
})
);