web-dev-qa-db-ja.com

angular 4リアクティブフォームで無効なコントロールを見つける方法

以下のような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を返しますが、すべてが正常に見えます。

私は、コントロールコレクションのステータスプロパティをチェックして見つけようとしました。しかし、無効なものを見つけてユーザーに表示する方法があるのだろうか?

50
sa_

すべてのコントロールを単純に繰り返して、ステータスを確認できます。

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;
  }
13
Jette

フォームとすべてのコントロールの両方が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
     })
1
LookForAngular

フォームにフィールドがあまりない場合は、F12キーを押してコントロールにカーソルを合わせると、フィールドの元の値/タッチされた値/有効な値を含むポップアップが表示されます-"#fieldname.form-control.ng- untouched.ng-invalid」。

1
darshna mishra

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;
}
0

フォームconsole.log(this.addCustomerForm.value)の値をログに記録できます。すべてのコントロールの値がコンソールに表示され、nullまたは ""(空)フィールドが無効なコントロールを示します

0
Sohail Anwar