角度4リアクティブ形式で無効なコントロールを見つける方法


92

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

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


エラーのあるフィールドを表示したいだけの場合は、cssを使用して無効なフィールドを強調表示または色付けできます。無効な各フィールドには、クラスリストに「ng-invalid」クラスが追加されています
LookForAngular 2018

回答:


175

すべてのコントロールを繰り返し処理して、ステータスを確認するだけです。

    public findInvalidControls() {
        const invalid = [];
        const controls = this.AddCustomerForm.controls;
        for (const name in controls) {
            if (controls[name].invalid) {
                invalid.push(name);
            }
        }
        return invalid;
    }

1
これに感謝しますが、私はこれを試しましたが、これでも何も返されません。フォームはまだ無効です。これは奇妙です。このコードは見栄えが良いのですが、form.validがfalseを返す理由は意味がありません
sa_ 2017

何がfindInvalidControls()あなたを返しますか?
Max Koretskyi 2017

1
何も返しません。無効は空です。デバッグウォッチ画面で1つずつ確認しましたが、すべてのコントロールは有効ですが、this.AddCustomerForm.validはまだfalseを返します。
sa_ 2017

わかったと思います。電子メールフィールドと正規表現がありますが、どういうわけかコントロールのステータスは
保留中

7
@ AngularInDepth.com-コントロールの1つがフォームグループの場合、関数は無効なフォームグループを返し、無効な特定のフォームコントロールは返しません
john Smith

36

私はこの問題と戦いました。すべてのフォームフィールドは有効ですが、それでもフォーム自体は無効です。

コントロールが動的に追加/削除されるFormArrayに「Validator.required」を設定したことがわかりました。したがって、FormArrayが空の場合でも、それは必須であり、したがって、表示されているすべてのコントロールが正しく入力されていても、フォームは常に無効でした。

'findInvalidControls'関数はFormControlのみをチェックし、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;
  }

3
信じられないほど便利な答え。ありがとうございました
Mikki

1
同意する、非常に有用な答え。
nenea

24

無効なAngularコントロールには、「ng-invalid」という名前CSSクラスがあります

ChromeのDevToolsで、[コンソール]タブを選択します。

コンソールプロンプトでコマンドを入力します。

document.getElementsByClassName('ng-invalid')

出力は次のようになります。 ここに画像の説明を入力してください

この場合、下線付きのテキストはフォームコントロール用listen-addressです。そして、丸で囲まれたテキスト:.ng-invalidコントロールが無効であることを示します。

注:クロムでテスト済み


2
これは私にとって、質問に答える最も直接的な方法のようです。
ckapilla

2
私があなたに飲み物を買うことができれば、あなたは私を狂わせることから救いました
AdamWinnipass20年

3

フォームとすべてのコントロールの両方が角度クラス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/11530

いずれの場合も、コントロールアクセサーを使用することで、フォーム内のすべての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
これは、空のコントロールがある場合でもnullを返します
sa_ 2017

1
エラーがない場合はnullを返す必要があります。テンプレートを投稿できますか?
lookForAngular 2017

ええ、これは機能しません。各フォームコントロールに異なる検証が設定されています。各フォームコントロールにはエラーが含まれていますが、フォームには含まれていません。Maximusが答えたようにコントロールを繰り返す必要があります。
AJT82 2017

this.form.controls ['Email']。errorsのような個々のコントロールのエラーにアクセスできます
Nazrul Muhaimin 2018

@ AJT_82確かに、formGroupにバリデーターが設定されている場合、フォーム自体にエラーが表示されることがあります(クロスフィールド検証に関するドキュメントを確認してください。これは、コントロールではなくグループで検証するのが理にかなっています)
LookForAngular

3

これで、Angular 9では、markAllAsTouched()メソッドを使用して、無効なコントロールバリデーターを表示できます。

this.AddCustomerForm.markAllAsTouched();

これに+1を付けると、ユーザーが必ずしも入力に触れていないときに検証メッセージを表示するという、私が知る必要のあることを見つけるのに役立ちました。
ショーンホール

1

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


1

this.form.updateValueAndValidity()それぞれのコントロールで同じメソッドを使用するか、実行してみるべきだと思います。


1

これを試して

 findInvalidControls(f: FormGroup) {
    const invalid = [];
    const controls = f.controls;
    for (const name in controls) {
      if (controls[name].invalid) {
        invalid.push(name);
      }
    }
    return invalid;
  }

1

これにより、コントロールのすべての名前がログに記録されます😊

for (let el in this.ReactiveForm.controls) {
      if (this.ReactiveForm.controls[el].errors) {
        console.log(el)
      }
 }          

これから配列または文字列を作成し、ユーザーに表示できます


0

私は自由にAngularInDepth.com- sコードを改善し、ネストされた形式の無効な入力も再帰的に検索するようにしました。FormArray-sまたはFormGroup-sのどちらでネストされているか。トップレベルのformGroupを入力するだけで、無効なすべてのFormControlが返されます。

FormControlチェックと無効な配列機能への追加を別の関数に分離する場合は、「instanceof」タイプのチェックの一部をすくい取ることができます。これにより、関数の見た目がかなりきれいになりますが、すべての無効なformControlのフラット配列を取得するために、グローバルな単一の関数オプションが必要でした。これが解決策です。

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

1
試しましたが、無効なFormGroupまたはFormArrayは見つかりませんでした...無効なFormControlのみです。私は同じ間違いをしました...私の答えを見てください。
Jette 2018

私はあなたのユースケースに合うように私の答えを改善しました。
Karl Johan Vallner 2018

0

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


-1

HTMLページで空またはnullのフォーム制御値を確認してください

フォームコントロールの値:{{formname.value | json}}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.