184 votes

Comment trouver les contrôles non valides sous forme réactionnelle angulaire 4

J'ai une forme réactive en angulaire comme ci-dessous:

 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 renvoie false, mais tout semble bien aller.

J'ai essayé de trouver avec vérifier la propriété status dans la collection de contrôles. Mais je me demande s’il existe un moyen de retrouver les invalides et de les afficher à l’utilisateur?

315voto

Maximus Points 1342

Vous pouvez simplement parcourir chaque contrôle et vérifier le statut:

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

62voto

Jette Points 723

Je viens de lutté contre ce problème: Chaque champ de formulaire est valide, mais encore la forme elle-même n'est pas valide.

S'avère que j'avais mis 'Validateur.required " sur un FormArray où les contrôles sont ajoutés/supprimés de façon dynamique. Donc, même si la FormArray était vide, il était encore nécessaire et, par conséquent, la forme est toujours valide, même si chaque contrôle visible a été correctement rempli.

Je n'ai pas trouvé la partie invalide de la forme, parce que mon " findInvalidControls fonction seulement vérifié FormControl et pas FormGroup/FormArray. J'ai donc mis à jour un peu:

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

5voto

LookForAngular Points 534

À la fois les formes et de toutes vos commandes de prolonger l'angle de classe AbstractControl. Chaque application a un accesseur pour les erreurs de validation.

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

L'api docs contient toutes les références https://angular.io/api/forms/AbstractControl

Modifier

Je pensais que l'erreur accesseur travaillé de cette façon, cependant, ce lien vers github montre qu'il y a d'autres personnes qui pensaient même que je n'ai https://github.com/angular/angular/issues/11530

Dans tous les cas, en utilisant les commandes de l'accesseur vous pouvez itérer sur tous les formControls dans votre formulaire.

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

2voto

Karl Johan Vallner Points 1179

J'ai pris la liberté d'améliorer AngularInDepth.com-s code, afin qu'il effectue une recherche récursive dans pour non valides entrées dans des formulaires imbriqués aussi. Si il être imbriquées par FormArray-s ou FormGroup-s. Il suffit de saisir le haut niveau formGroup et il sera de retour tous les FormControls qui ne sont pas valides.

Vous pouvez éventuellement écrémé certains de la "instanceof" les vérifications de type suite, si vous souhaitez séparer les FormControl de vérifier et de plus non valide éventail de fonctionnalités dans une fonction séparée. Cela rendrait la fonction look beaucoup plus propre, mais j'avais besoin d'un mondial, unique fonction, l'option pour obtenir un tableau plat toutes les invalides formControls et c'est la solution!

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

Juste pour ceux qui en ont besoin, de sorte qu'ils n'ont pas de code d'eux-mêmes..

Edit #1

Il a été demandé qu'il renvoie également invalide FormArray-s et FormGroups, donc si vous avez besoin aussi, utilisez ce 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;
}

1voto

darshna mishra Points 11

Si vous n'avez pas beaucoup de champs dans le formulaire, vous pouvez simplement F12 et survoler le contrôle, vous pourrez voir la fenêtre contextuelle avec les valeurs immaculées / touchées / valides du champ- "# fieldname.form-control.ng- untouched.ng-invalid ".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X