以下のようなAngularにリアクティブフォームがあります。
this.AddCustomerForm = this.formBuilder.group({
Firstname: ['', Validators.required],
Lastname: ['', Validators.required],
Email: ['', Validators.required, Validators.pattern(this.EMAIL_REGEX)],
Picture: [''],
Username: ['', Validators.required],
Password: ['', Validators.required],
Address: ['', Validators.required],
Postcode: ['', Validators.required],
City: ['', Validators.required],
Country: ['', Validators.required]
});
createCustomer(currentCustomer: Customer)
{
if (!this.AddCustomerForm.valid)
{
//some app logic
}
}
this.AddCustomerForm.validはfalseを返しますが、すべてが正常に見えます。
私は、コントロールコレクションのステータスプロパティをチェックして見つけようとしました。しかし、無効なものを見つけてユーザーに表示する方法があるのだろうか?
すべてのコントロールを単純に繰り返して、ステータスを確認できます。
public findInvalidControls() {
const invalid = [];
const controls = this.AddCustomerForm.controls;
for (const name in controls) {
if (controls[name].invalid) {
invalid.Push(name);
}
}
return invalid;
}
私はこの問題と戦いました。すべてのフォームフィールドは有効ですが、それでもフォーム自体は無効です。
コントロールが動的に追加/削除されるFormArrayに 'Validator.required'を設定したことがわかりました。そのため、FormArrayが空だったとしても、それはまだ必要だったため、すべての表示コントロールが正しく入力されていても、フォームは常に無効でした。
私の 'findInvalidControls'関数はFormControl/FormArrayのみをチェックし、FormGroup/FormArrayはチェックしなかったため、フォームの無効な部分は見つかりませんでした。だから私はそれを少し更新しました:
/*
Returns an array of invalid control/group names, or a zero-length array if
no invalid controls/groups where found
*/
public findInvalidControlsRecursive(formToInvestigate:FormGroup|FormArray):string[] {
var invalidControls:string[] = [];
let recursiveFunc = (form:FormGroup|FormArray) => {
Object.keys(form.controls).forEach(field => {
const control = form.get(field);
if (control.invalid) invalidControls.Push(field);
if (control instanceof FormGroup) {
recursiveFunc(control);
} else if (control instanceof FormArray) {
recursiveFunc(control);
}
});
}
recursiveFunc(formToInvestigate);
return invalidControls;
}
フォームとすべてのコントロールの両方がangularクラスAbstractControlを拡張します。各実装には、検証エラーへのアクセサーがあります。
let errors = this.AddCustomerForm.errors
// errors is an instance of ValidatorErrors
APIドキュメントには、すべての参照が含まれています https://angular.io/api/forms/AbstractControl
編集
エラーアクセサーはこのように機能すると思ったが、githubへのこのリンクは、私と同じと思った他の人がいることを示しています https://github.com/angular/angular/issues/115
いずれの場合でも、コントロールアクセサーを使用すると、フォーム内のすべてのformControlを反復処理できます。
Object.keys(this.AddCustomerForm.controls)
.forEach( control => {
//check each control here
// if the child is a formGroup or a formArray
// you may cast it and check it's subcontrols too
})
フォームにフィールドがあまりない場合は、F12キーを押してコントロールにカーソルを合わせると、フィールドの元の値/タッチされた値/有効な値を含むポップアップが表示されます-"#fieldname.form-control.ng- untouched.ng-invalid」。
AngularInDepth.com-sコードを改善するために自由を取り、ネストされた形式で無効な入力も再帰的に検索します。 FormArray-sまたはFormGroup-sによってネストされるかどうか。最上位のformGroupを入力するだけで、無効なすべてのFormControlが返されます。
FormControlチェックと無効な配列機能への追加を別の関数に分離する場合、「instanceof」型チェックの一部をスキミングできます。これにより、関数はずっときれいに見えますが、すべての無効なformControlsのフラット配列を取得するためのグローバルな単一関数オプションが必要でした。これが解決策です。
findInvalidControls( _input: AbstractControl, _invalidControls: AbstractControl[] ): AbstractControl[] {
if ( ! _invalidControls ) _invalidControls = [];
if ( _input instanceof FormControl ) {
if ( _input.invalid ) _invalidControls.Push( _input );
return _invalidControls;
}
if ( ! (_input instanceof FormArray) && ! (_input instanceof FormGroup) ) return _invalidControls;
const controls = _input.controls;
for (const name in controls) {
let control = controls[name];
switch( control.constructor.name )
{
case 'AbstractControl':
case 'FormControl':
if (control.invalid) _invalidControls.Push( control );
break;
case 'FormArray':
(<FormArray> control ).controls.forEach( _control => _invalidControls = findInvalidControls( _control, _invalidControls ) );
break;
case 'FormGroup':
_invalidControls = findInvalidControls( control, _invalidControls );
break;
}
}
return _invalidControls;
}
必要な人のためだけに、自分でコーディングする必要はありません。
編集#1
無効なFormArray-sおよびFormGroupsも返すように要求されたため、必要な場合はこのコードを使用してください
findInvalidControls( _input: AbstractControl, _invalidControls: AbstractControl[] ): AbstractControl[] {
if ( ! _invalidControls ) _invalidControls = [];
if ( _input instanceof FormControl ) {
if ( _input.invalid ) _invalidControls.Push( _input );
return _invalidControls;
}
if ( ! (_input instanceof FormArray) && ! (_input instanceof FormGroup) ) return _invalidControls;
const controls = _input.controls;
for (const name in controls) {
let control = controls[name];
if (control.invalid) _invalidControls.Push( control );
switch( control.constructor.name )
{
case 'FormArray':
(<FormArray> control ).controls.forEach( _control => _invalidControls = findInvalidControls( _control, _invalidControls ) );
break;
case 'FormGroup':
_invalidControls = findInvalidControls( control, _invalidControls );
break;
}
}
return _invalidControls;
}
フォームconsole.log(this.addCustomerForm.value)
の値をログに記録できます。すべてのコントロールの値がコンソールに表示され、nullまたは ""(空)フィールドが無効なコントロールを示します