我有一个Angular 2应用程序,它使用ReactiveForms
模块来管理使用自定义验证器的表单。验证器接收FormControl
对象。我有一些输入字段可以使用相同的自定义验证器,只要我知道FormControl
传递给验证器时字段的名称。
我在FormControl
上找不到任何暴露输入字段名称的方法或公共属性。当然,它很容易看到它的价值。以下显示了我想如何使用它:
public asyncValidator(control: FormControl): {[key: string]: any} {
var theFieldName = control.someMethodOfGettingTheName(); // this is the missing piece
return new Promise(resolve => {
this.myService.getValidation(theFieldName, control.value)
.subscribe(
data => {
console.log('Validation success:', data);
resolve(null);
},
err => {
console.log('Validation failure:', err);
resolve(err._body);
});
});
}
我们可以使用.parent
属性,今天["_parent"]
(见下文):
export const getControlName = (control: ng.forms.AbstractControl) =>
{
var controlName = null;
var parent = control["_parent"];
// only such parent, which is FormGroup, has a dictionary
// with control-names as a key and a form-control as a value
if (parent instanceof ng.forms.FormGroup)
{
// now we will iterate those keys (i.e. names of controls)
Object.keys(parent.controls).forEach((name) =>
{
// and compare the passed control and
// a child control of a parent - with provided name (we iterate them all)
if (control === parent.controls[name])
{
// both are same: control passed to Validator
// and this child - are the same references
controlName = name;
}
});
}
// we either found a name or simply return null
return controlName;
}
现在我们准备调整验证器定义了
public asyncValidator(control: FormControl): {[key: string]: any} {
//var theFieldName = control.someMethodOfGettingTheName(); // this is the missing piece
var theFieldName = getControlName(control);
...
.parent
later, ["_parent"]
now目前(今天,现在),当前版本是:
但是关注这个问题:feat(forms): make 'parent' a public property of 'AbstractControl'
正如这里已经说过的那样
特征
- 形式:使'父'成为'AbstractControl'的公共财产(#11855)(445e592)
- ...
我们以后可以把["_parent"]
变成.parent
扩展RadimKöhler的答案。这是编写该功能的较短方式。
getControlName(c: AbstractControl): string | null {
const formGroup = c.parent.controls;
return Object.keys(formGroup).find(name => c === formGroup[name]) || null;
}
您有两种选择:
在Attribute
装饰的帮助下:
constructor(@Attribute('formControlName') public formControlName) {}
在Input
装饰的帮助下:
@Input() formControlName;
要使用它,您的验证当然需要是一个指令。
从Angular 4.2.x开始,您可以使用公共父属性访问FormControl
的父级FormGroup
(及其控件):
private formControl: FormControl;
//...
Object.keys(this.formControl.parent.controls).forEach((key: string) => {
// ...
});
您可以在验证器中设置控件名称:
this.form = this.fb.group({
controlName: ['', [Validators.required, (c) => this.validate(c, 'controlName')]]
});
然后:
validate(c: FormControl, name) {
return name === 'controlName' ? {invalid: true} : null;
}
不完全是您想要的,但您可以像在某些示例中那样动态创建验证器。
喜欢
typeBasedValidator(controlName: string): ValidatorFn {
return(control: AbstractControl): {[key: string]: any} => {
// Your code using controlName to validate
if(controlName == "something") {
doSomething();
} else {
doSomethingElse();
}
}
}
然后在创建表单时使用验证器,传递控件名称