动态 FormControl 验证
Dynamic FormControl Validation
我有一个表单控件,它是通过带有索引的 ngFor 生成的。
<input formControlName='answerControl{{i}}' type="textbox" name="" value="{{ question.answer }}">
如果最小长度不是 4,我如何向这个特定的 formControl 添加验证。
在我的组件中我有:
this.answer_0 = new FormControl(this.questionsArr[0][2], Validators.minLength(4));
当我尝试时:
<div *ngIf="answerControl{{i}}.valid">Error</div>
我遇到错误,无法完成。
完整的 TS 代码:
@Component({
selector: 'app-fp-edit-pvq',
templateUrl: './fp-pvq.component.html',
animations: [
trigger('hideShow', [
state('hide', style({
opacity: 0,
height: 0
})),
state('show', style({
opacity: 1,
height: '*'
})),
transition('hide => show', animate('150ms ease-in')),
transition('show => hide', animate('150ms ease-out'))
])
]
})
export class FpPVQ implements OnInit {
constructor( private _pvqStepUp: PVQStepUpService, private _langToggle: ErrorToggleService ) { }
private questions: any;
private lang: string;
private counter: number = 0;
private checkedLimit: number = 5;
private updateMode: boolean = false;
private createMode: boolean = false;
private deadlinePassed: boolean = false;
private pvqForm:FormGroup;
private answer_0:FormControl;
private answer_1:FormControl;
private answer_2:FormControl;
private answer_3:FormControl;
private answer_4:FormControl;
private answer_5:FormControl;
private answer_6:FormControl;
private answer_7:FormControl;
private answer_8:FormControl;
private answer_9:FormControl;
private answer_10:FormControl;
private answer_11:FormControl;
private answer_12:FormControl;
private answer_13:FormControl;
private answer_14:FormControl;
private answer_15:FormControl;
private answer_16:FormControl;
private answer_17:FormControl;
private answer_18:FormControl;
private answer_19:FormControl;
private answerControlArr: Array<FormControl> = [];
private questionsArr: Array<any> = [];
ngOnInit() {
this.lang = document['locale'];
console.log('fpPVQ:: pvqStepUpData --> {}, ', this._pvqStepUp.data);
if(this._pvqStepUp.data != null){
this.questions = this._pvqStepUp.data.pvqs;
this.questions.forEach(object => {
this.questionsArr.push([object.question_EN, object.question_FR, object.answer]);
})
if(this._pvqStepUp.data.deadlinePassed)
this.deadlinePassed = true;
}
this.answer_0 = new FormControl(this.questionsArr[0][2], Validators.required);
this.answer_1 = new FormControl(this.questionsArr[1][2], Validators.required);
this.answer_2 = new FormControl(this.questionsArr[2][2], Validators.required);
this.answer_3 = new FormControl(this.questionsArr[3][2], Validators.required);
this.answer_4 = new FormControl(this.questionsArr[4][2], Validators.required);
this.answer_5 = new FormControl(this.questionsArr[5][2], Validators.required);
this.answer_6 = new FormControl(this.questionsArr[6][2], Validators.required);
this.answer_7 = new FormControl(this.questionsArr[7][2], Validators.required);
this.answer_8 = new FormControl(this.questionsArr[8][2], Validators.required);
this.answer_9 = new FormControl(this.questionsArr[9][2], Validators.required);
this.answer_10 = new FormControl(this.questionsArr[10][2], Validators.required);
this.answer_11 = new FormControl(this.questionsArr[11][2], Validators.required);
this.answer_12 = new FormControl(this.questionsArr[12][2], Validators.required);
this.answer_13 = new FormControl(this.questionsArr[13][2], Validators.required);
this.answer_14 = new FormControl(this.questionsArr[14][2], Validators.required);
this.answer_15 = new FormControl(this.questionsArr[15][2], Validators.required);
this.answer_16 = new FormControl(this.questionsArr[16][2], Validators.required);
this.answer_17 = new FormControl(this.questionsArr[17][2], Validators.required);
this.answer_18 = new FormControl(this.questionsArr[18][2], Validators.required);
this.answer_19 = new FormControl(this.questionsArr[19][2], Validators.required);
this.answerControlArr.push(this.answer_0);
this.answerControlArr.push(this.answer_1);
this.answerControlArr.push(this.answer_2);
this.answerControlArr.push(this.answer_3);
this.answerControlArr.push(this.answer_4);
this.answerControlArr.push(this.answer_5);
this.answerControlArr.push(this.answer_6);
this.answerControlArr.push(this.answer_7);
this.answerControlArr.push(this.answer_8);
this.answerControlArr.push(this.answer_9);
this.answerControlArr.push(this.answer_10);
this.answerControlArr.push(this.answer_11);
this.answerControlArr.push(this.answer_12);
this.answerControlArr.push(this.answer_13);
this.answerControlArr.push(this.answer_14);
this.answerControlArr.push(this.answer_15);
this.answerControlArr.push(this.answer_16);
this.answerControlArr.push(this.answer_17);
this.answerControlArr.push(this.answer_18);
this.answerControlArr.push(this.answer_19);
this.pvqForm = new FormGroup({
answerControl0: this.answer_0,
answerControl1: this.answer_1,
answerControl2: this.answer_2,
answerControl3: this.answer_3,
answerControl4: this.answer_4,
answerControl5: this.answer_5,
answerControl6: this.answer_6,
answerControl7: this.answer_7,
answerControl8: this.answer_8,
answerControl9: this.answer_9,
answerControl10: this.answer_10,
answerControl11: this.answer_11,
answerControl12: this.answer_12,
answerControl13: this.answer_13,
answerControl14: this.answer_14,
answerControl15: this.answer_15,
answerControl16: this.answer_16,
answerControl17: this.answer_17,
answerControl18: this.answer_18,
answerControl19: this.answer_19
});
this.questions.sort((a,b) => {
//This sorts all the entries
if(a.answer > b.answer) return -1;
});
//Determine if Update or Create
if(this._pvqStepUp.data.flow !== 'CREATE'){
this.createMode = true;
this.counter = 0;
} else {
this.updateMode = true;
this.counter = 5;
}
this._langToggle.getLanguage().subscribe(
lang => {
this.lang = lang.toString();
});
}
checkedState(event, checkBox){
if(event.target.checked === true){
if(this.counter < this.checkedLimit){
this.counter++;
} else {
event.target.checked = false;
}
} else if(this.counter > 0){
let index = event.target.name;
console.log('index is ', index);
console.log('Answer Control Array is ', this.answerControlArr);
console.log('Answer control is ', this.answerControlArr[index])
this.counter--;
}
}
onSubmit(pvqForm: any) {
console.log('4176-21 Submitted data --> {}', pvqForm);
console.log(pvqForm._value);
Object.keys(pvqForm._value).map((key) => {
console.log('4176-21 Object Key: ', key, ' Object Value: ', pvqForm._value[key]);
})
}
}
完整 HTML:
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="container-generic bg-rbc-white">
<div class="row">
<div class="container-generic col-md-12">
<h1>Some Message about PVQS</h1>
<p>Maecenas sed diam eget risus varius blandit sit amet non magna. Maecenas faucibus mollis interdum.</p>
</div>
</div>
<form [formGroup]="pvqForm" (ngSubmit)="onSubmit(pvqForm)" novalidate>
<div *ngFor="let question of questions; let i = index" class="row container-generic">
<div class="col-md-8">
<div class="container-input-checkbox">
<label class="container-flex">
<input #checkBox class="pvq-create-checkbox" type="checkbox" name="{{i}}" (change)="checkedState($event, checkBox)" [checked]="question.answer">
<div class="pvq-create-label">
<div *ngIf="lang == 'en'">
<p>{{ question.question_EN }}</p>
</div>
<div *ngIf="lang == 'fr'">
<p>{{ question.question_FR }}</p>
</div>
</div>
</label>
<label [@hideShow]="checkBox.checked ? 'show' : 'hide'" >Answer
<input minlength=4 formControlName='answerControl{{i}}' type="textbox" name="{{i}}" value="{{ question.answer }}">
<div *ngIf="!{{i}}.valid" class="inline-validation critical">
<p>Error</p>
</div>
</label>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button [disabled]="pvqForm.invalid" class="button-primary" aria-label="Continue" type="submit">Continue</button>
<button *ngIf="deadlinePassed" class="button-secondary">Postpone</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
您可以使用 minlength
指令添加 minlength
验证器:
<input minlength=4 formControlName='answerControl{{i}}' type="textbox" name="" value="{{ question.answer }}">
您还需要在验证中使用以下语法来定位特定控件div:
<div *ngIf="!pvqForm.controls['answerControl' + i].valid">Error here</div>
Here is the plunker 显示解决方案和相关代码:
TS
export class AppComponent {
questions = [
new FormControl('0'),
new FormControl('1'),
new FormControl('2')
];
pvqForm = new FormGroup({
answerControl0: this.questions[0],
answerControl1: this.questions[1],
answerControl2: this.questions[2],
});
HTML
<form [formGroup]="pvqForm" novalidate>
<div *ngFor="let question of questions; let i = index">
<input minlength=4 formControlName='answerControl{{i}}' type="text" name="{{i}}">
<div *ngIf="!pvqForm.controls['answerControl' + i].valid" class="inline-validation critical">
<p>Error</p>
</div>
</div>
</form>
您可能还想添加对 touched
状态的检查
pvqForm.controls['answerControl' + i].touched
因此只有在与控件进行交互时才会显示错误:
<div *ngIf="!pvqForm.controls['answerControl' + i].valid && pvqForm.controls['answerControl' + i].touched" ...>
您也可以在组件中手动设置验证器class:
pvqForm.answerControl0.setValidators(Validators.minLength(4))
您的模板应如下所示
<input minlength="4" formControlName='answerControl{{i}}' type="textbox" name="" value="{{ question.answer }}">
并在您的 .ts 文件中
this.answer_0 = new FormControl(this.questionsArr[0][2], Validators.required);
也尝试将 novalidate
添加到表单元素 <form.... novalidate>
我有一个表单控件,它是通过带有索引的 ngFor 生成的。
<input formControlName='answerControl{{i}}' type="textbox" name="" value="{{ question.answer }}">
如果最小长度不是 4,我如何向这个特定的 formControl 添加验证。
在我的组件中我有:
this.answer_0 = new FormControl(this.questionsArr[0][2], Validators.minLength(4));
当我尝试时:
<div *ngIf="answerControl{{i}}.valid">Error</div>
我遇到错误,无法完成。
完整的 TS 代码:
@Component({
selector: 'app-fp-edit-pvq',
templateUrl: './fp-pvq.component.html',
animations: [
trigger('hideShow', [
state('hide', style({
opacity: 0,
height: 0
})),
state('show', style({
opacity: 1,
height: '*'
})),
transition('hide => show', animate('150ms ease-in')),
transition('show => hide', animate('150ms ease-out'))
])
]
})
export class FpPVQ implements OnInit {
constructor( private _pvqStepUp: PVQStepUpService, private _langToggle: ErrorToggleService ) { }
private questions: any;
private lang: string;
private counter: number = 0;
private checkedLimit: number = 5;
private updateMode: boolean = false;
private createMode: boolean = false;
private deadlinePassed: boolean = false;
private pvqForm:FormGroup;
private answer_0:FormControl;
private answer_1:FormControl;
private answer_2:FormControl;
private answer_3:FormControl;
private answer_4:FormControl;
private answer_5:FormControl;
private answer_6:FormControl;
private answer_7:FormControl;
private answer_8:FormControl;
private answer_9:FormControl;
private answer_10:FormControl;
private answer_11:FormControl;
private answer_12:FormControl;
private answer_13:FormControl;
private answer_14:FormControl;
private answer_15:FormControl;
private answer_16:FormControl;
private answer_17:FormControl;
private answer_18:FormControl;
private answer_19:FormControl;
private answerControlArr: Array<FormControl> = [];
private questionsArr: Array<any> = [];
ngOnInit() {
this.lang = document['locale'];
console.log('fpPVQ:: pvqStepUpData --> {}, ', this._pvqStepUp.data);
if(this._pvqStepUp.data != null){
this.questions = this._pvqStepUp.data.pvqs;
this.questions.forEach(object => {
this.questionsArr.push([object.question_EN, object.question_FR, object.answer]);
})
if(this._pvqStepUp.data.deadlinePassed)
this.deadlinePassed = true;
}
this.answer_0 = new FormControl(this.questionsArr[0][2], Validators.required);
this.answer_1 = new FormControl(this.questionsArr[1][2], Validators.required);
this.answer_2 = new FormControl(this.questionsArr[2][2], Validators.required);
this.answer_3 = new FormControl(this.questionsArr[3][2], Validators.required);
this.answer_4 = new FormControl(this.questionsArr[4][2], Validators.required);
this.answer_5 = new FormControl(this.questionsArr[5][2], Validators.required);
this.answer_6 = new FormControl(this.questionsArr[6][2], Validators.required);
this.answer_7 = new FormControl(this.questionsArr[7][2], Validators.required);
this.answer_8 = new FormControl(this.questionsArr[8][2], Validators.required);
this.answer_9 = new FormControl(this.questionsArr[9][2], Validators.required);
this.answer_10 = new FormControl(this.questionsArr[10][2], Validators.required);
this.answer_11 = new FormControl(this.questionsArr[11][2], Validators.required);
this.answer_12 = new FormControl(this.questionsArr[12][2], Validators.required);
this.answer_13 = new FormControl(this.questionsArr[13][2], Validators.required);
this.answer_14 = new FormControl(this.questionsArr[14][2], Validators.required);
this.answer_15 = new FormControl(this.questionsArr[15][2], Validators.required);
this.answer_16 = new FormControl(this.questionsArr[16][2], Validators.required);
this.answer_17 = new FormControl(this.questionsArr[17][2], Validators.required);
this.answer_18 = new FormControl(this.questionsArr[18][2], Validators.required);
this.answer_19 = new FormControl(this.questionsArr[19][2], Validators.required);
this.answerControlArr.push(this.answer_0);
this.answerControlArr.push(this.answer_1);
this.answerControlArr.push(this.answer_2);
this.answerControlArr.push(this.answer_3);
this.answerControlArr.push(this.answer_4);
this.answerControlArr.push(this.answer_5);
this.answerControlArr.push(this.answer_6);
this.answerControlArr.push(this.answer_7);
this.answerControlArr.push(this.answer_8);
this.answerControlArr.push(this.answer_9);
this.answerControlArr.push(this.answer_10);
this.answerControlArr.push(this.answer_11);
this.answerControlArr.push(this.answer_12);
this.answerControlArr.push(this.answer_13);
this.answerControlArr.push(this.answer_14);
this.answerControlArr.push(this.answer_15);
this.answerControlArr.push(this.answer_16);
this.answerControlArr.push(this.answer_17);
this.answerControlArr.push(this.answer_18);
this.answerControlArr.push(this.answer_19);
this.pvqForm = new FormGroup({
answerControl0: this.answer_0,
answerControl1: this.answer_1,
answerControl2: this.answer_2,
answerControl3: this.answer_3,
answerControl4: this.answer_4,
answerControl5: this.answer_5,
answerControl6: this.answer_6,
answerControl7: this.answer_7,
answerControl8: this.answer_8,
answerControl9: this.answer_9,
answerControl10: this.answer_10,
answerControl11: this.answer_11,
answerControl12: this.answer_12,
answerControl13: this.answer_13,
answerControl14: this.answer_14,
answerControl15: this.answer_15,
answerControl16: this.answer_16,
answerControl17: this.answer_17,
answerControl18: this.answer_18,
answerControl19: this.answer_19
});
this.questions.sort((a,b) => {
//This sorts all the entries
if(a.answer > b.answer) return -1;
});
//Determine if Update or Create
if(this._pvqStepUp.data.flow !== 'CREATE'){
this.createMode = true;
this.counter = 0;
} else {
this.updateMode = true;
this.counter = 5;
}
this._langToggle.getLanguage().subscribe(
lang => {
this.lang = lang.toString();
});
}
checkedState(event, checkBox){
if(event.target.checked === true){
if(this.counter < this.checkedLimit){
this.counter++;
} else {
event.target.checked = false;
}
} else if(this.counter > 0){
let index = event.target.name;
console.log('index is ', index);
console.log('Answer Control Array is ', this.answerControlArr);
console.log('Answer control is ', this.answerControlArr[index])
this.counter--;
}
}
onSubmit(pvqForm: any) {
console.log('4176-21 Submitted data --> {}', pvqForm);
console.log(pvqForm._value);
Object.keys(pvqForm._value).map((key) => {
console.log('4176-21 Object Key: ', key, ' Object Value: ', pvqForm._value[key]);
})
}
}
完整 HTML:
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="container-generic bg-rbc-white">
<div class="row">
<div class="container-generic col-md-12">
<h1>Some Message about PVQS</h1>
<p>Maecenas sed diam eget risus varius blandit sit amet non magna. Maecenas faucibus mollis interdum.</p>
</div>
</div>
<form [formGroup]="pvqForm" (ngSubmit)="onSubmit(pvqForm)" novalidate>
<div *ngFor="let question of questions; let i = index" class="row container-generic">
<div class="col-md-8">
<div class="container-input-checkbox">
<label class="container-flex">
<input #checkBox class="pvq-create-checkbox" type="checkbox" name="{{i}}" (change)="checkedState($event, checkBox)" [checked]="question.answer">
<div class="pvq-create-label">
<div *ngIf="lang == 'en'">
<p>{{ question.question_EN }}</p>
</div>
<div *ngIf="lang == 'fr'">
<p>{{ question.question_FR }}</p>
</div>
</div>
</label>
<label [@hideShow]="checkBox.checked ? 'show' : 'hide'" >Answer
<input minlength=4 formControlName='answerControl{{i}}' type="textbox" name="{{i}}" value="{{ question.answer }}">
<div *ngIf="!{{i}}.valid" class="inline-validation critical">
<p>Error</p>
</div>
</label>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button [disabled]="pvqForm.invalid" class="button-primary" aria-label="Continue" type="submit">Continue</button>
<button *ngIf="deadlinePassed" class="button-secondary">Postpone</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
您可以使用 minlength
指令添加 minlength
验证器:
<input minlength=4 formControlName='answerControl{{i}}' type="textbox" name="" value="{{ question.answer }}">
您还需要在验证中使用以下语法来定位特定控件div:
<div *ngIf="!pvqForm.controls['answerControl' + i].valid">Error here</div>
Here is the plunker 显示解决方案和相关代码:
TS
export class AppComponent {
questions = [
new FormControl('0'),
new FormControl('1'),
new FormControl('2')
];
pvqForm = new FormGroup({
answerControl0: this.questions[0],
answerControl1: this.questions[1],
answerControl2: this.questions[2],
});
HTML
<form [formGroup]="pvqForm" novalidate>
<div *ngFor="let question of questions; let i = index">
<input minlength=4 formControlName='answerControl{{i}}' type="text" name="{{i}}">
<div *ngIf="!pvqForm.controls['answerControl' + i].valid" class="inline-validation critical">
<p>Error</p>
</div>
</div>
</form>
您可能还想添加对 touched
状态的检查
pvqForm.controls['answerControl' + i].touched
因此只有在与控件进行交互时才会显示错误:
<div *ngIf="!pvqForm.controls['answerControl' + i].valid && pvqForm.controls['answerControl' + i].touched" ...>
您也可以在组件中手动设置验证器class:
pvqForm.answerControl0.setValidators(Validators.minLength(4))
您的模板应如下所示
<input minlength="4" formControlName='answerControl{{i}}' type="textbox" name="" value="{{ question.answer }}">
并在您的 .ts 文件中
this.answer_0 = new FormControl(this.questionsArr[0][2], Validators.required);
也尝试将 novalidate
添加到表单元素 <form.... novalidate>