Как получить имя поля ввода из объекта Angular2 FormControl?
У меня есть приложение 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);
});
});
}
Ответы
Ответ 1
Мы можем использовать свойство .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
позже, ["_parent"]
Теперь
На данный момент (сегодня, сейчас) текущий выпуск:
2.1.2 (2016-10-27)
Но следуя этой проблеме: feat (forms): make 'parent' публичное свойство 'AbstractControl'
И как уже сказано здесь
2.2.0-beta.0 (2016-10-20)
Характеристики
- forms: make 'parent' public property 'AbstractControl' (# 11855) (445e592)
- ...
мы могли бы позже изменить ["_parent"]
на .parent
Ответ 2
Чтобы расширить ответ Радима Кёлера. вот более короткий способ написания этой функции.
getControlName(c: AbstractControl): string | null {
const formGroup = c.parent.controls;
return Object.keys(formGroup).find(name => c === formGroup[name]) || null;
}
Ответ 3
У вас есть два варианта:
С помощью декоратора Attribute
:
constructor(@Attribute('formControlName') public formControlName) {}
С помощью декоратора Input
:
@Input() formControlName;
Чтобы использовать это, ваша проверка должна быть директивой, конечно.
Ответ 4
Начиная с FormControl
Angular 4.2.x вы можете получить доступ к родительской FormGroup
FormControl
FormGroup
(и ее элементам управления), используя общедоступное родительское свойство:
private formControl: FormControl;
//...
Object.keys(this.formControl.parent.controls).forEach((key: string) => {
// ...
});
Ответ 5
Вы можете установить имя элемента управления в валидаторах:
this.form = this.fb.group({
controlName: ['', [Validators.required, (c) => this.validate(c, 'controlName')]]
});
А потом:
validate(c: FormControl, name) {
return name === 'controlName' ? {invalid: true} : null;
}
Ответ 6
Не совсем то, что вы хотите, но вы можете динамически создавать валидатор, как в некоторых примерах.
как
typeBasedValidator(controlName: string): ValidatorFn {
return(control: AbstractControl): {[key: string]: any} => {
// Your code using controlName to validate
if(controlName == "something") {
doSomething();
} else {
doSomethingElse();
}
}
}
Затем используйте валидатор при создании формы, передав управляющее имя, например