So finden Sie die ungültigen Kontrollen in Winkel 4 reaktiver Form


89

Ich habe eine reaktive Form in Angular wie folgt:

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 gibt false zurück, aber alles sieht gut aus.

Ich habe versucht, die Statuseigenschaft in der Steuerelementauflistung zu überprüfen. Aber ich frage mich, ob es eine Möglichkeit gibt, die ungültigen zu finden und dem Benutzer anzuzeigen?


Wenn Sie nur die Felder mit einem Fehler anzeigen möchten, können Sie CSS verwenden, um die ungültigen Felder hervorzuheben oder einzufärben. Jedes ungültige Feld hat eine "ng-ungültige" Klasse in seiner Klassenliste
LookForAngular

Antworten:


168

Sie können einfach jedes Steuerelement durchlaufen und den Status überprüfen:

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

1
Danke dafür, aber ich habe es versucht und selbst das gibt nichts zurück. Mein Formular ist immer noch ungültig. Das ist seltsam. Ich meine, dieser Code sieht gut aus, aber es macht keinen Sinn, warum form.valid false zurückgibt
sa_

Was bringt findInvalidControls()dich zurück?
Max Koretskyi

1
es gibt nichts zurück, ungültig ist leer. Ich habe nacheinander im Debug-Überwachungsbildschirm überprüft, dass alle Steuerelemente gültig sind, aber this.AddCustomerForm.valid gibt immer noch false zurück.
Sa_

Ich glaube ich habe es herausgefunden. Es gibt ein E-Mail-Feld und einen regulären Ausdruck, aber irgendwie ist der Status des Steuerelements PENDING und es könnte die Ursache sein
sa_

6
@ AngularInDepth.com - Wenn eines der Steuerelemente eine Formulargruppe ist, gibt Ihre Funktion die ungültige Formulargruppe zurück und nicht das spezifische Formularsteuerelement, das ungültig ist
John Smith

35

Ich habe gerade dieses Problem bekämpft: Jedes Formularfeld ist gültig, aber das Formular selbst ist immer noch ungültig.

Es stellte sich heraus, dass ich 'Validator.required' in einem FormArray festgelegt hatte, in dem Steuerelemente dynamisch hinzugefügt / entfernt werden. Selbst wenn das FormArray leer war, war es dennoch erforderlich und daher war das Formular immer ungültig, selbst wenn jedes sichtbare Steuerelement korrekt ausgefüllt war.

Ich habe den ungültigen Teil des Formulars nicht gefunden, da meine Funktion 'findInvalidControls' nur die FormControl und nicht FormGroup / FormArray überprüft hat. Also habe ich es ein bisschen aktualisiert:

/* 
   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
Unglaublich nützliche Antwort. Vielen Dank
Mikki

1
Stimme zu, sehr nützliche Antwort.
Nenea

20

Wählen Sie unter DevTools in Chrome die Registerkarte Konsole aus.

Geben Sie in der Eingabeaufforderung der Konsole den folgenden Befehl ein:

document.getElementsByClassName('ng-invalid')

Die Ausgabe sollte ungefähr so ​​aussehen: Geben Sie hier die Bildbeschreibung ein

In diesem Fall dient der unterstrichene Text zur Formularsteuerung listen-address. Und der eingekreiste Text: .ng-invalidzeigt an, dass das Steuerelement ungültig ist.

Hinweis: In Chrom getestet


2
Dies scheint mir der direkteste Weg zu sein, um die Frage zu beantworten.
Ckapilla

2
Du hast mich
davor bewahrt

3

Sowohl die Formulare als auch alle Ihre Steuerelemente erweitern die Winkelklasse AbstractControl. Jede Implementierung verfügt über einen Zugriff auf die Validierungsfehler.

let errors = this.AddCustomerForm.errors
// errors is an instance of ValidatorErrors

Die API-Dokumente enthalten alle Verweise https://angular.io/api/forms/AbstractControl

Bearbeiten

Ich dachte, der Fehler-Accessor funktioniert so, aber dieser Link zu Github zeigt, dass es einige andere Leute gibt, die genauso dachten wie ich https://github.com/angular/angular/issues/11530

In jedem Fall können Sie mit dem Steuerelement-Accessor alle formControls in Ihrem Formular durchlaufen.

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
Dies gibt null zurück, auch wenn leere Steuerelemente vorhanden sind
sa_

1
Es sollte null zurückgeben, wenn keine Fehler vorliegen. Können Sie Ihre Vorlage veröffentlichen?
LookForAngular

Ja, das wird nicht funktionieren, die unterschiedlichen Validierungen, die für jedes Formularsteuerelement festgelegt wurden, die einzelnen Formularsteuerelemente enthalten ihre Fehler, das Formular nicht. Sie müssen die Steuerelemente wiederholen, die Maximus beantwortet hat.
AJT82

Ich kann auf Fehler für jedes einzelne Contorls wie this.form.controls ['Email']
zugreifen

@ AJT_82 In der Tat kann das Formular selbst Fehler anzeigen, wenn ein Validator für die formGroup festgelegt wurde (überprüfen Sie die Dokumente zur feldübergreifenden Validierung, was für die Validierung in der Gruppe und nicht im Steuerelement
sinnvoll ist

3

In Winkel 9 können Sie jetzt die Methode markAllAsTouched () verwenden, um die ungültigen Steuerelementvalidatoren anzuzeigen:

this.AddCustomerForm.markAllAsTouched();

Ich werde dies mit +1 bewerten, da es mir dabei geholfen hat, herauszufinden, was ich wissen muss - nämlich Validierungsmeldungen anzuzeigen, wenn der Benutzer die Eingaben nicht unbedingt berührt hat.
Sean Halls

1

Wenn Sie nicht viele Felder im Formular haben, können Sie einfach F12 drücken und mit der Maus über das Steuerelement fahren. Sie können das Popup mit den makellosen / berührten / gültigen Werten des Felds sehen - "# fieldname.form-control.ng- untouched.ng-invalid ".


1

Ich denke, Sie sollten versuchen this.form.updateValueAndValidity(), dieselbe Methode in jedem der Steuerelemente zu verwenden oder auszuführen.


1

Versuche dies

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

1

Dadurch werden alle Namen der Steuerelemente log protokolliert

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

Sie können daraus ein Array oder einen String erstellen und dem Benutzer anzeigen


0

Ich habe mir erlaubt , den AngularInDepth.com- Code so zu verbessern , dass er auch in verschachtelten Formen rekursiv nach ungültigen Eingaben sucht. Ob es von FormArray-s oder FormGroup-s verschachtelt wird. Geben Sie einfach die oberste FormGroup ein und es werden alle ungültigen FormControls zurückgegeben.

Sie können möglicherweise einige der Typprüfungen "instanceof" überfliegen, wenn Sie die FormControl-Prüfung und die Hinzufügung zu ungültigen Array-Funktionen in eine separate Funktion trennen würden. Dies würde die Funktion viel sauberer aussehen lassen, aber ich brauchte eine globale Option mit einer einzigen Funktion, um ein flaches Array aller ungültigen formControls zu erhalten, und dies ist die Lösung!

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

Nur für diejenigen, die es brauchen, damit sie es nicht selbst codieren müssen.

Bearbeiten Sie # 1

Es wurde angefordert, dass auch ungültige FormArray-s und FormGroups zurückgegeben werden. Wenn Sie dies ebenfalls benötigen, verwenden Sie diesen Code

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
Ich habe es versucht, aber es findet keine ungültige FormGroup oder FormArray ... nur ungültige FormControls. Ich habe den gleichen Fehler gemacht ... siehe meine Antwort.
Jette

Ich habe meine Antwort verbessert, um sie an Ihren Anwendungsfall anzupassen.
Karl Johan Vallner

0

Sie können den Wert des Formulars protokollieren console.log(this.addCustomerForm.value). Es tröstet den Wert aller Steuerelemente. Dann zeigen null oder "" (leere) Felder ungültige Steuerelemente an

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.