ReactiveForms
モジュールを使用してカスタムバリデーターを使用するフォームを管理するAngular 2アプリケーションがあります。バリデーターは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;
}
これで、validator定義を調整する準備ができました。
public asyncValidator(control: FormControl): {[key: string]: any} {
//var theFieldName = control.someMethodOfGettingTheName(); // this is the missing piece
var theFieldName = getControlName(control);
...
.parent
後で、["_parent"]
今現時点では(today、now)、現在のリリースは次のとおりです。
しかし、この問題に続いて: feat(forms): 'parent'を '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;
}
Angular 4.2.xでは、public parentプロパティを使用してFormControl
の親FormGroup
(およびそのコントロール)にアクセスできます。 :
private formControl: FormControl;
//...
Object.keys(this.formControl.parent.controls).forEach((key: string) => {
// ...
});
次の2つのオプションがあります。
Attribute
デコレータの助けを借りて:
constructor(@Attribute('formControlName') public formControlName) {}
Input
デコレータの助けを借りて:
@Input() formControlName;
これを使用するには、検証がもちろんディレクティブである必要があります。
バリデーターにコントロール名を設定できます:
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();
}
}
}
次に、フォームの作成時にバリデーターを使用して、次のようなコントロール名を渡します