Angular2反应形式表
Posted
技术标签:
【中文标题】Angular2反应形式表【英文标题】:Angular2 Reactive Form Table 【发布时间】:2017-12-22 15:11:19 【问题描述】:我在查找和尝试做我想做的事情时遇到了一些麻烦。
我有一个表,每行都有输入,我希望使用 ngFor 创建的每一行都被视为一个表单组。
在每个表单组中,我想要验证,如果在行中填充了任何控件,则需要在完成提交之前填充整个表单组。
这是我目前模板中的内容。
我在组件中还没有任何东西,因为 Angular.io 并且搜索了几个小时并没有显示任何接近我想要的东西。
<form>
<table id="table" class="mdl-data-table mdl-js-data-table mdl-data-table mdl-shadow--2dp">
<thead>
<tr>
<th>Day</th>
<th>Description</th>
<th>Open Time</th>
<th>Close Time</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let scheduleDetail of scheduleDetails">
<td style="padding: 0 8px 0 8px;">weekdayConverter(scheduleDetail.dayId)</td>
<td class="pad-input">
<mdl-textfield style="max-width:100px;" type="text" class="font" name="description" [(ngModel)]="scheduleDetail.description"></mdl-textfield>
</td>
<td>
<mdl-textfield style="max-width:75px" type="text" error-msg="hh:mm" name="openTime" pattern="([01]\d|2[0-3]):?([0-5]\d)" [(ngModel)]="scheduleDetail.openTime"></mdl-textfield>
</td>
<td>
<mdl-textfield style="max-width:75px" type="text" error-msg="hh:mm" name="closeTime" pattern="([01]\d|2[0-3]):?([0-5]\d)" [(ngModel)]="scheduleDetail.closeTime"></mdl-textfield>
</td>
</tr>
</tbody>
</table>
</form>
更新
在模板中添加了以下内容:
将输入更改为:
<mdl-textfield (keyup)="formChange(scheduleDetail)" style="max-width:100px;" type="text" class="font" name="description" [(ngModel)]="scheduleDetail.description"></mdl-textfield>
在组件中添加了以下内容:
formChange(detail:scheduleDetail)
if(this.checkValid(detail)==false)
this.scheduleDetails.filter(detail => detail == detail)[0].require=true;
else
this.scheduleDetails.filter(detail => detail == detail)[0].require=false;
this.checkForm();
checkValid(detail:scheduleDetail)
if(detail.description!=null && detail.description!="")
if(this.checkTime(detail))
return true
else
return false
else
return true
checkTime(detail:scheduleDetail)
if(
(detail.openTime!=null && detail.closeTime!=null) &&
( detail.openTime!="" && detail.closeTime!="") &&
(this.checkRegExp(detail.openTime) && this.checkRegExp(detail.closeTime))
)
return true
else if((this.checkRegExp(detail.openTime) && this.checkRegExp(detail.closeTime)))
return true
else return false
checkRegExp(time:string)
let timeRegExp = /([01]\d|2[0-3]):?([0-5]\d)/;
if(timeRegExp.test(time))
return true;
else
return false;
checkForm()
let valid: boolean = true;
this.scheduleDetails.forEach(detail =>
if(detail.require==true)
valid = false;
);
this.scheduleDetails.forEach(detail =>
if(detail.description=="" || detail.description==null)
valid = false;
);
this.formValid = valid;
【问题讨论】:
【参考方案1】:模型驱动的表单
您使用的是模板驱动的表单,难以扩展和维护。
在这里,我将指导您迁移到模型驱动的表单。
组件
export class WeekScheduleComponent
// Our empty Form
myForm: FormGroup;
constructor(private fb: FormBuilder)
// We inject FormBuilder to our component
// Now, we instantiate myForm with FormBuilder
// Notice that myForm is a FormGroup which contains an empty FormArray
this.myForm = this.fb.group(
scheduleDetail: this.fb.array([])
)
addRow()
// This function instantiates a FormGroup for each day
// and pushes it to our FormArray
// We get our FormArray
const control = <FormArray>this.myForm.controls['scheduleDetail'];
// instantiate a new day FormGroup;
newDayGroup: FormGroup = this.initItems();
// Add it to our formArray
control.push(newDayGroup);
initItems(): FormGroup
// Here, we make the form for each day
return this.fb.group(
description: [null, Validators.required],
openTime: [null, Validators.required],
closeTime: [null, Validators.required]
);
submit()
// do stuff and submit result
console.log(this.myForm.value);
在您的模板中:
<form [formGroup]="myForm" *ngIf="myForm">
<table formArrayName="scheduleDetail">
<tr *ngFor="let item of myForm.controls.scheduleDetail.controls; let i=index"
[formGroupName]="i" >
<td><input type='text' formControlName="description"></td>
<td><input type='text' formControlName="openTime"></td>
<td><input type='text' formControlName="closeTime"></td>
</tr>
</table>
</form>
<button (click)="addRow()">Add new item</button>
<button (click)="submit()" [disabled]="!myForm.valid">Submit</button>
【讨论】:
我很难遵循这个。我的表将包含 7 行,一周中的每一天都有 1 行。当我尝试适应和理解时,您在 ngFor 中的部分让我感到困惑。所以每个 tr 都可以充当一个表单组,并且为它动态保留一个表单组变量,以便我可以引用其中的控件。我想我在这里有点过头了.... 不,实际上并不难。但我会更详细地更新,以便您理解代码。你知道,我需要睡一会儿。现在是凌晨 5 点。在这里。 我最终只是将很多 if 与我的所有验证链接在一起,并得到了相同的结果。用我所做的更新帖子,以防将来对某人有所帮助。【参考方案2】:组件
import Component, OnInit from '@angular/core';
import FormGroup, FormBuilder, FormControl, Validators, FormArray from '@angular/forms';
@Component(
selector: 'app-sales',
templateUrl: './sales.component.html',
styleUrls: ['./sales.component.css']
)
export class SalesComponent implements OnInit
myForm: FormGroup;
constructor(private fb: FormBuilder)
// getter to get a reference to scheduleDetail form array in myForm form group
get scheduleDetail():FormArray
return <FormArray>this.myForm.get('scheduleDetail')
// add a new row, get reference to form array using getter method and push form group into it
addRow()
this.scheduleDetail.push(this.initItems());
// make a form for each row!
initItems(): FormGroup
return this.fb.group(
description: [null, Validators.required],
openTime: [null, Validators.required],
closeTime: [null, Validators.required]
);
submit()
console.log(this.myForm.value)
ngOnInit()
this.myForm = this.fb.group(
scheduleDetail: this.fb.array([this.initItems()])
)
模板
<form [formGroup]="myForm" *ngIf="myForm">
<table formArrayName="scheduleDetail">
<thead>
<tr>
<th >Desc</th>
<th >Open Time</th>
<th >Close Time</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of myForm.controls.scheduleDetail.controls; let i=index"
[formGroupName]="i" >
<td><input type='text' formControlName="description"></td>
<td><input type='text' formControlName="openTime"></td>
<td><input type='text' formControlName="closeTime"></td>
</tr>
</tbody>
</table>
</form>
<button (click)="addRow()">Add new item</button>
<button (click)="submit()" [disabled]="!myForm.valid">Submit</button>
【讨论】:
以上是关于Angular2反应形式表的主要内容,如果未能解决你的问题,请参考以下文章