我有这些字段:
field1
field2
field3
field4
this.form = this.formbuilder.group({
'field1' = ['', [<control-specific-validations>]],
'field2' = ['', [<control-specific-validations>]]
}, { validator: isField1GreaterThanField2Validator}
});
我需要更多验证:
- field3.value must be greater than field4.value
- field3.value must be greater than field2.value + 1
- field4.value must be less than field1.value
如何将这些新的验证要求整合到构建的表单中?
我做不想要做的是设置
formControl.valueChanges.subscribe(value => { });
每个字段的然后有很多if / else。
然后我可以删除整个反应形式模块,使用2way-databinding并在验证表达式为真时在ui中呈现错误字符串。
答案 0 :(得分:2)
您可以使用自定义验证程序执行此操作。 https://angular.io/guide/form-validation#custom-validators
以下是您想要的工作示例:https://stackblitz.com/edit/isgreaterthanotherfield-custom-validator
验证器功能本身如下所示:
greaterThan(field: string): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} => {
const group = control.parent;
const fieldToCompare = group.get(field);
const isLessThan = Number(fieldToCompare.value) > Number(control.value);
return isLessThan ? {'lessThan': {value: control.value}} : null;
}
}
我在控件上使用parent
属性来访问其他字段。
请注意,您无法在表单初始化中设置该验证程序,因为尚未定义基于它的字段。
this.myForm = this.fb.group({
field1: 0,
field2: 0
});
this.myForm.get('field2').setValidators(this.greaterThan('field1'));
更新:我更进一步,实现了一个自定义验证器,它接受谓词函数,因此您可以使用相同的验证器进行所有比较。
在此处查看此行动:https://stackblitz.com/edit/comparison-custom-validator
它使用与上面相同的方法,但由于您可以传递任何比较,因此更灵活一些。有一些边缘情况,例子没有考虑,比如传递一个不存在的表单字段名称,如果你传递的表单字段实际上没有使用数字/类型不匹配等,但我相信超出了问题的范围。
这是一个有趣的问题,我很乐意研究它。
为了快速参考,以下是使用灵活的自定义验证器整个组件的外观:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
myForm: FormGroup;
field2HasError: boolean;
field3HasError: boolean;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.myForm = this.fb.group({
field1: 0,
field2: 0,
field3: 0,
field4: 0
});
const field1MustBeGreaterThanField2 =
this.comparison('field1', (field2Val, field1Val) => {
return Number(field2Val) < Number(field1Val);
});
const field3MustBeGreaterThanField2Plus1 =
this.comparison('field2', (field3Val, field2Val) => {
return Number(field3Val) > (Number(field2Val) + 1);
});
this.myForm.get('field2').setValidators(field1MustBeGreaterThanField2);
this.myForm.get('field3').setValidators(field3MustBeGreaterThanField2Plus1);
this.myForm.get('field2').valueChanges.subscribe(() => {
this.field2HasError = this.myForm.get('field2').hasError('comparison');
});
this.myForm.get('field3').valueChanges.subscribe(() => {
this.field3HasError = this.myForm.get('field3').hasError('comparison');
});
}
comparison(field: string, predicate: (fieldVal, fieldToCompareVal) => boolean): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} => {
const group = control.parent;
const fieldToCompare = group.get(field);
console.log('fieldToCompare.value', fieldToCompare.value);
console.log('field.value', control.value);
const valid = predicate(control.value, fieldToCompare.value);
return valid ? null : {'comparison': {value: control.value}};
}
}
}
答案 1 :(得分:0)
//你的.ts
ngOnInit() {
this.myForm = this.fb.group({
field1: 0,
field2: 0,
field3: 0,
}, { validator: this.customValidator }); //a unique validator
}
customValidator(formGroup: FormGroup) {
let errors:any={};
let i:number=0;
let valueBefore:any=null;
Object.keys(formGroup.controls).forEach(field => {
const control = formGroup.get(field);
if (valueBefore)
{
if (parseInt(control.value)<valueBefore)
{
let newError:any={['errorLess'+i]:true} //create an object like,e.g. {errorLess1:true}
errors={...errors,...newError}; //Concat errors
}
}
valueBefore=parseInt(control.value);
i++;
});
if (errors)
return errors;
}
}
.html喜欢
<form [formGroup]="myForm">
field1:
<input formControlName="field1">
<br> field2:
<input formControlName="field2">
<div *ngIf="myForm.hasError('errorLess1')">Field 2 less that field 1</div>
<br> field3:
<input formControlName="field3">
<div *ngIf="myForm.hasError('errorLess2')">Field 3 less that field 2</div>
</form>