Angular 反应式表单 - 交叉控制验证
Angular Forms reactive - cross-control validation
我正在为 angular 5 中的反应式表单开发验证器,但在设置基于另一个输入值的验证器时遇到困难。
表格看起来像这样:
let myRules = new FormArray([]);
myRules.push(this.newRuleFormGroup(1, 'period', 1));
this.myForm = new FormGroup({
'name': new FormControl(name, [Validators.required, this.validate_usedName.bind(this)]), // V: must not exist already
'icon': new FormControl(icon, [Validators.required]), // has default
'rules': myRules
})
'rules' 是一个 FormArray
,我使用以下方法从模板中推送新的 FormGroup
:
newRuleFormGroup = (amount: number, period: string, repAmount: number = 1) => {
return new FormGroup({
'amount': new FormControl(amount, [Validators.required]),
'type': new FormControl(period, [Validators.required]),
'repAmount': new FormControl(repAmount, [this.validate_repAmount.bind(this)])
})
}
repAmount
仅在type == "period"
时才需要。在 repAmount
的验证器中,我试图联系父 FormGroup
并尝试获取其子 'type'
控件的值。像这样:
validate_repAmount(control:FormControl): {[s:string]: boolean}{
let type = control.parent.get('type');// Cannot read property 'get' of undefined
let controlValue = control.value;
console.log(control.parent); // returns the parent FormGroup object
if(type.value == 'period' && (controlValue != '' || controlValue>0)) {
return {'repAmountMissing':true};
}
return null;
}
但我一直收到错误提示 Cannot read property 'get' of undefined
。如果我尝试 console.log(control.parent)
,我会按预期获得 FormGroup 对象,但我似乎无法使用其属性以任何方式访问它。
任何人都可以建议一种方法来为验证器访问同一组中的 'type' 值吗?
您应该按如下方式包装您的代码:
if (parent) { YOUR_VALIDATION_GOES_HERE }
我曾经遇到过同样的问题,我就是这样解决的。
更新:你可以试试这个。
validate_repAmount(control: FormControl): { [s: string]: boolean } {
const parent = control.parent;
if (parent) {
let type = parent.get('type');
let controlValue = control.value;
if (type.value == 'period' && (controlValue != '' || controlValue > 0)) {
return { 'repAmountMissing': true };
}
}
return null;
}
任何时候你想做一些交叉验证,你应该将验证登录移动到祖先控件。在这种情况下,它将是您的 FormGroup
.
import { Component } from '@angular/core';
import { ValidatorFn, FormBuilder, FormGroup, Validators } from '@angular/forms';
const validator: ValidatorFn = (fg: FormGroup) => {
const rep = fg.get('repAmount');
const type = fg.get('type');
const required = type.value === 'period' ? Validators.required(rep) : null;
return required ? required: null;
}
@Component({
selector: 'my-app',
template: `
<form [formGroup]="form">
<input formControlName="type" placeholder="type">
<input formControlName="repAmount" placeholder="repAmount" >
</form>
{{ form.valid }}
`,
styles: [`
input: { width: 100% }
`]
})
export class AppComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
repAmount: [null],
type: [null]
}, { validator });
const repCtrl = this.form.get('repAmount')
this.form.statusChanges.pipe(
map(status => status === 'INVALID'),
map(invalid => invalid ? { err: true } : null)
).subscribe(err => repCtrl.setErrors(err, { emitEvent: false }))
}
}
我正在为 angular 5 中的反应式表单开发验证器,但在设置基于另一个输入值的验证器时遇到困难。
表格看起来像这样:
let myRules = new FormArray([]);
myRules.push(this.newRuleFormGroup(1, 'period', 1));
this.myForm = new FormGroup({
'name': new FormControl(name, [Validators.required, this.validate_usedName.bind(this)]), // V: must not exist already
'icon': new FormControl(icon, [Validators.required]), // has default
'rules': myRules
})
'rules' 是一个 FormArray
,我使用以下方法从模板中推送新的 FormGroup
:
newRuleFormGroup = (amount: number, period: string, repAmount: number = 1) => {
return new FormGroup({
'amount': new FormControl(amount, [Validators.required]),
'type': new FormControl(period, [Validators.required]),
'repAmount': new FormControl(repAmount, [this.validate_repAmount.bind(this)])
})
}
repAmount
仅在type == "period"
时才需要。在 repAmount
的验证器中,我试图联系父 FormGroup
并尝试获取其子 'type'
控件的值。像这样:
validate_repAmount(control:FormControl): {[s:string]: boolean}{
let type = control.parent.get('type');// Cannot read property 'get' of undefined
let controlValue = control.value;
console.log(control.parent); // returns the parent FormGroup object
if(type.value == 'period' && (controlValue != '' || controlValue>0)) {
return {'repAmountMissing':true};
}
return null;
}
但我一直收到错误提示 Cannot read property 'get' of undefined
。如果我尝试 console.log(control.parent)
,我会按预期获得 FormGroup 对象,但我似乎无法使用其属性以任何方式访问它。
任何人都可以建议一种方法来为验证器访问同一组中的 'type' 值吗?
您应该按如下方式包装您的代码:
if (parent) { YOUR_VALIDATION_GOES_HERE }
我曾经遇到过同样的问题,我就是这样解决的。
更新:你可以试试这个。
validate_repAmount(control: FormControl): { [s: string]: boolean } {
const parent = control.parent;
if (parent) {
let type = parent.get('type');
let controlValue = control.value;
if (type.value == 'period' && (controlValue != '' || controlValue > 0)) {
return { 'repAmountMissing': true };
}
}
return null;
}
任何时候你想做一些交叉验证,你应该将验证登录移动到祖先控件。在这种情况下,它将是您的 FormGroup
.
import { Component } from '@angular/core';
import { ValidatorFn, FormBuilder, FormGroup, Validators } from '@angular/forms';
const validator: ValidatorFn = (fg: FormGroup) => {
const rep = fg.get('repAmount');
const type = fg.get('type');
const required = type.value === 'period' ? Validators.required(rep) : null;
return required ? required: null;
}
@Component({
selector: 'my-app',
template: `
<form [formGroup]="form">
<input formControlName="type" placeholder="type">
<input formControlName="repAmount" placeholder="repAmount" >
</form>
{{ form.valid }}
`,
styles: [`
input: { width: 100% }
`]
})
export class AppComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
repAmount: [null],
type: [null]
}, { validator });
const repCtrl = this.form.get('repAmount')
this.form.statusChanges.pipe(
map(status => status === 'INVALID'),
map(invalid => invalid ? { err: true } : null)
).subscribe(err => repCtrl.setErrors(err, { emitEvent: false }))
}
}