Come trovare i controlli non validi in forma reattiva angolare 4


92

Ho una forma reattiva in Angular come di seguito:

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 restituisce false, ma sembra tutto a posto.

Ho provato a trovare controllando la proprietà status nella raccolta dei controlli. Ma mi chiedo se esiste un modo per trovare quelli non validi e mostrarli all'utente?


Se vuoi solo visualizzare i campi con un errore, puoi usare css per evidenziare o colorare i campi non validi. Ogni campo non valido ha una classe "ng-invalid" aggiunta al suo elenco di classi
LookForAngular

Risposte:


176

Puoi semplicemente iterare su ogni controllo e controllare lo stato:

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

1
grazie per questo ma ho provato questo e anche questo non restituisce nulla il mio modulo è ancora non valido, questo è strano. Voglio dire che questo codice sembra buono ma non ha alcun senso perché form.valid restituisca false
sa_

cosa findInvalidControls()ti restituisce?
Max Koretskyi

1
non restituisce nulla, non valido è vuoto. Ho controllato uno per uno nella schermata di controllo del debug, tutti i controlli sono validi ma this.AddCustomerForm.valid restituisce ancora false.
sa_

Penso di averlo scoperto. c'è un campo email e un'espressione regolare ma in qualche modo lo stato del controllo è IN ATTESA e potrebbe essere la causa
sa_

7
@ AngularInDepth.com - se uno dei controlli è un gruppo di moduli, la tua funzione restituirà il gruppo di moduli non valido e non il controllo specifico del modulo che non è valido
john Smith

36

Ho appena affrontato questo problema: ogni campo del modulo è valido, ma il modulo stesso non è valido.

Si scopre che avevo impostato "Validator.required" su un FormArray in cui i controlli vengono aggiunti / rimossi dinamicamente. Quindi, anche se il FormArray era vuoto, era ancora necessario e quindi il modulo era sempre non valido, anche se ogni controllo visibile era stato riempito correttamente.

Non ho trovato la parte non valida del modulo, perché la mia funzione "findInvalidControls" controllava solo FormControl e non FormGroup / FormArray. Quindi l'ho aggiornato un po ':

/* 
   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
Risposta incredibilmente utile. Grazie mille
Mikki

1
D'accordo, risposta molto utile.
nenea

24

Un controllo angolare non valido ha la classe CSS denominata "ng-invalid" .

In DevTools in Chrome, seleziona la scheda Console.

Nel prompt della console digitare il comando:

document.getElementsByClassName('ng-invalid')

L'output dovrebbe essere simile a questo: inserisci qui la descrizione dell'immagine

In questo caso, il testo sottolineato è per il controllo del modulo listen-address. E il testo cerchiato: .ng-invalidindica che il controllo non è valido.

Nota: testato in cromo


2
questo a me sembra essere il modo più diretto per rispondere alla domanda.
ckapilla

2
Mi hai salvato dall'impazzire, se solo potessi offrirti da bere
Adam Winnipass

3

Sia i moduli che tutti i controlli estendono la classe angolare AbstractControl. Ogni implementazione ha una funzione di accesso agli errori di convalida.

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

La documentazione api contiene tutti i riferimenti https://angular.io/api/forms/AbstractControl

modificare

Pensavo che la funzione di accesso all'errore funzionasse in questo modo, tuttavia questo collegamento a GitHub mostra che ci sono altre persone che la pensavano come me https://github.com/angular/angular/issues/11530

In ogni caso, utilizzando la funzione di accesso ai controlli è possibile iterare su tutti i formControls nel modulo.

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
questo restituisce null anche se ci sono controlli vuoti
sa_

1
Dovrebbe restituire null quando non ci sono errori. Puoi pubblicare il tuo modello?
LookForAngular

Sì, questo non funzionerà, le diverse convalide impostate su ogni controllo del modulo, quei controlli di ciascun modulo contengono i loro errori, il modulo no. È necessario iterare i controlli come Maximus ha dato la risposta.
AJT82

Posso accedere agli errori per ogni singolo contorl come this.form.controls ['Email'].
Errors

@ AJT_82 infatti il ​​Form stesso può mostrare errori se è stato impostato un validatore per formGroup (controlla i documenti sulla validazione cross field, che ha senso convalidare sul gruppo e non nel controllo)
LookForAngular

3

Ora, nell'angolo 9, puoi usare il metodo markAllAsTouched () per mostrare i validatori dei controlli non validi:

this.AddCustomerForm.markAllAsTouched();

Dare a questo un +1, in quanto mi ha aiutato a scoprire cosa avevo bisogno di sapere --- che è mostrare messaggi di convalida quando l'utente non ha necessariamente toccato gli input.
Sean Halls

1

Se non hai molti campi nel modulo, puoi semplicemente F12 e passare il mouse sul controllo, sarai in grado di vedere il pop-up con i valori immacolati / toccati / validi del campo- "# fieldname.form-control.ng- untouched.ng-invalid ".


1

Penso che dovresti provare a utilizzare this.form.updateValueAndValidity()o provare a eseguire lo stesso metodo in ciascuno dei controlli.


1

prova questo

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

1

Questo registrerà tutti i nomi dei controlli 😊

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

puoi creare un array o una stringa da questo e visualizzarlo all'utente


0

Mi sono preso la libertà di migliorare AngularInDepth.com codice di , in modo che cerchi in modo ricorsivo anche gli input non validi in forme annidate. Sia che sia annidato da FormArray-s o FormGroup-s. Basta inserire il formGroup di primo livello e restituirà tutti i FormControls non validi.

È possibile eliminare alcuni dei controlli di tipo "instanceof", se si separa il controllo FormControl e l'aggiunta alla funzionalità di matrice non valida in una funzione separata. Ciò renderebbe la funzione molto più pulita, ma avevo bisogno di un'opzione globale, singola funzione per ottenere un array piatto di tutti i formControls non validi e questa è la soluzione!

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

Solo per coloro che ne hanno bisogno, quindi non devono codificarlo da soli ..

Modifica n. 1

È stato richiesto che restituisca anche FormArray e FormGroup non validi, quindi se ne hai bisogno, usa questo codice

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
L'ho provato, ma non trova alcun FormGroup o FormArray non valido ... solo FormControl non valido. Ho fatto lo stesso errore ... vedi la mia risposta.
Jette

Ho migliorato la mia risposta, per adattarla al tuo caso d'uso.
Karl Johan Vallner

0

puoi registrare il valore del modulo console.log(this.addCustomerForm.value), consolerà il valore di tutti i controlli quindi i campi null o "" (vuoti) indicano controlli non validi


0

Se desideri verificare se il modulo è valido o meno e non desideri apportare modifiche al codice, puoi provare a eseguire il seguente comando nella Console degli strumenti per sviluppatori di Chrome. Assicurati che la tua app angolare mostri il componente che ospita il modulo in questione.

ng.probe(document.querySelector("app-your-component-selector-name")).componentInstance;

Non dimenticare di sostituire il nome del selettore dei componenti nel comando precedente.

Questo comando elencherà tutte le variabili dal tuo componente incluso AddCustomerForm. Ora se espandi questo, vedrai l'elenco di tutti i tuoi controlli. È quindi possibile espandere ogni controllo per verificare se è valido o meno.


-1

Controlla il valore di controllo del modulo vuoto o nullo nella pagina html

Valore controlli modulo: {{formname.value | json}}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.