web-dev-qa-db-fra.com

Validation du déclencheur de tous les champs dans Angular Form submit

J'utilise cette méthode: http://plnkr.co/edit/A6gvyoXbBd2kfToPmiiA?p=preview pour valider uniquement les champs sur le flou. Cela fonctionne bien, mais je souhaite également les valider (et ainsi afficher les erreurs éventuelles pour ces champs) lorsque l'utilisateur clique sur le bouton "Soumettre" (il ne s'agit pas d'un véritable envoi, mais d'un appel de données à une fonction).

Existe-t-il un moyen de déclencher à nouveau la validation de tous les champs en cliquant sur ce bouton?

77
Maarten

Ce qui a fonctionné pour moi, c’est d’utiliser la fonction $setSubmitted, qui apparaît pour la première fois dans la documentation angulaire de la version 1.3.20.

Dans l'événement de clic où je voulais déclencher la validation, j'ai procédé comme suit:

vm.triggerSubmit = function() {
    vm.homeForm.$setSubmitted();
    ...
}

C'était tout ce qu'il me fallait. Selon la documentation, il "définit le formulaire à son état soumis". C'est mentionné ici .

42
developering

Je sais, il est un peu trop tard pour répondre, mais tout ce que vous avez à faire est de forcer toutes les formes à se salir. Jetez un coup d'œil à l'extrait suivant:

angular.forEach($scope.myForm.$error.required, function(field) {
    field.$setDirty();
});

et ensuite vous pouvez vérifier si votre formulaire est valide en utilisant:

if($scope.myForm.$valid) {
    //Do something
}   

et enfin, je suppose que vous voudriez changer votre itinéraire si tout semble bien aller: 

$location.path('/somePath');

Edit : form ne s'enregistrera pas lui-même sur la portée tant que l'événement submit n'est pas déclenché. Il suffit d’utiliser la directive ng-submit pour appeler une fonction et encapsuler ce qui précède dans cette fonction, et cela devrait fonctionner. 

41
Thilak Rao

Au cas où quelqu'un reviendrait à cela plus tard ... Aucune de ces réponses ne fonctionnait pour moi. J'ai donc creusé dans les entrailles de la validation de forme angulaire et trouvé la fonction appelée pour exécuter des validateurs sur un champ donné. Cette propriété s'appelle commodément $validate

Si vous avez un formulaire nommé myForm, vous pouvez appeler par programmation myForm.my_field.$validate() pour exécuter la validation de champ. Par exemple:

<div ng-form name="myForm">
    <input required name="my_field" type="text" ng-blur="myForm.my_field.$validate()">
</div>

Notez que l'appel de $validate a des implications pour votre modèle. À partir de la documentation angulaire pour ngModelCtrl. $ Validate:

Exécute chacun des validateurs inscrits (d'abord des validateurs synchrones, puis des validateurs asynchrones). Si la validité devient invalide, le modèle sera défini sur non défini, à moins que ngModelOptions.allowInvalid ne soit pas vrai. Si la validité devient valide, le modèle sera défini sur la dernière valeur $ modelValue valide, c'est-à-dire la dernière valeur analysée ou la dernière valeur définie dans l'étendue.

Par conséquent, si vous envisagez d'utiliser quelque chose avec la valeur de modèle non valide (par exemple, afficher un message pour le leur dire), vous devez vous assurer que allowInvalid est défini sur true pour votre modèle.

14
chukkwagon

Vous pouvez utiliser Angular-Validator pour faire ce que vous voulez. C'est simple à utiliser.

Ce sera:

  • Validez seulement les champs sur $dirty ou sur submit
  • Empêcher le formulaire d'être soumis s'il est invalide
  • Afficher le message d'erreur personnalisé après la saisie du champ $dirty ou l'envoi du formulaire

Voir la démo

Exemple

<form angular-validator 
       angular-validator-submit="myFunction(myBeautifulForm)"
       name="myBeautifulForm">
       <!-- form fields here -->
    <button type="submit">Submit</button>
</form>

Si le champ ne passe pas le validator, l'utilisateur ne pourra pas soumettre le formulaire.

Consultez des cas d'utilisation et des exemples de validateur d'angle pour plus d'informations.

_ {Disclaimer: Je suis l'auteur de Angular-Validator} _

12
user3920706

Eh bien, la manière angulaire serait de laisser le logiciel gérer la validation, car cela change à chaque changement de modèle, et d'afficher le résultat à l'utilisateur, quand vous le souhaitez.

Dans ce cas, vous décidez quand afficher les erreurs, il vous suffit de définir un indicateur: http://plnkr.co/edit/0NNppKKhbLTYMZaxMQ9l?p=preview

Autant que je sache, un problème nous a été posé pour nous permettre un contrôle de formulaire plus avancé. Puisqu'il n'est pas résolu, je l'utiliserais au lieu de réinventer toutes les méthodes de validation existantes.

edit: Mais si vous insistez, voici votre violon modifié avec validation avant soumission. http://plnkr.co/edit/Xfr7X6JXPhY9lFL3hnOw?p=preview Le contrôleur diffuse un événement lorsque l'utilisateur clique sur le bouton et que la directive effectue la magie de validation.

11
Oliver

Une approche consiste à forcer tous les attributs à être sales. Vous pouvez le faire dans chaque contrôleur, mais cela devient très compliqué. Il serait préférable d'avoir une solution générale.

Le moyen le plus simple auquel je pouvais penser était d'utiliser une directive

  • il gérera l'attribut submit du formulaire 
  • itère à travers tous les champs de formulaire et marque les champs vierges sales 
  • il vérifie si le formulaire est valide avant d'appeler la fonction submit

Voici la directive

myModule.directive('submit', function() {
  return {
    restrict: 'A',
    link: function(scope, formElement, attrs) {
      var form;
      form = scope[attrs.name];
      return formElement.bind('submit', function() {
        angular.forEach(form, function(field, name) {
          if (typeof name === 'string' && !name.match('^[\$]')) {
            if (field.$pristine) {
              return field.$setViewValue(field.$value);
            }
          }
        });
        if (form.$valid) {
          return scope.$apply(attrs.submit);
        }
      });
    }
  };
});

Et mettez à jour votre formulaire HTML, par exemple:

 <form ng-submit='justDoIt()'>

devient:

 <form name='myForm' novalidate submit='justDoIt()'>

Voir un exemple complet ici: http://plunker.co/edit/QVbisEK2WEbORTAWL7Gu?p=preview

9
joshnuss

Voici ma fonction globale pour afficher les messages d'erreur de formulaire.

 function show_validation_erros(form_error_object) {
        angular.forEach(form_error_object, function (objArrayFields, errorName) {
            angular.forEach(objArrayFields, function (objArrayField, key) {
                objArrayField.$setDirty();
            });
        });
    };

Et dans mes contrôleurs,

if ($scope.form_add_sale.$invalid) { 
    $scope.global.show_validation_erros($scope.form_add_sale.$error);
}
3
Namal

Sur la base de la réponse de Thilak, j'ai pu proposer cette solution ...

Comme mes champs de formulaire ne montrent que des messages de validation si un champ est invalide et que l'utilisateur a touché le contact, j'ai pu utiliser ce code déclenché par un bouton pour afficher mes champs invalides

// Show/trigger any validation errors for this step
angular.forEach(vm.rfiForm.stepTwo.$error, function(error) {
  angular.forEach(error, function(field) {
    field.$setTouched();
  });
});
// Prevent user from going to next step if current step is invalid
if (!vm.rfiForm.stepTwo.$valid) {
  isValid = false;
}
<!-- form field -->
<div class="form-group" ng-class="{ 'has-error': rfi.rfiForm.stepTwo.Parent_Suffix__c.$touched && rfi.rfiForm.stepTwo.Parent_Suffix__c.$invalid }">

  <!-- field label -->
  <label class="control-label">Suffix</label>
  <!-- end field label -->
  <!-- field input -->
  <select name="Parent_Suffix__c" class="form-control"
          ng-options="item.value as item.label for item in rfi.contact.Parent_Suffixes"
          ng-model="rfi.contact.Parent_Suffix__c" />
  <!-- end field input -->
  <!-- field help -->
  <span class="help-block" ng-messages="rfi.rfiForm.stepTwo.Parent_Suffix__c.$error" ng-show="rfi.rfiForm.stepTwo.Parent_Suffix__c.$touched">
    <span ng-message="required">this field is required</span>
  </span>  
  <!-- end field help -->
</div>
<!-- end form field -->

2
Charles Naccio

Pour valider tous les champs de mon formulaire quand je le souhaite, je fais une validation sur chaque champ de contrôles $$ comme ceci:

angular.forEach($scope.myform.$$controls, function (field) {
    field.$validate();
});
1
stephaneb

Note: Je sais que c'est un hack, mais c'était utile pour Angular 1.2 et les versions antérieures qui ne fournissaient pas un mécanisme simple.

La validation déclenche l'événement change. Par conséquent, certaines choses telles que la modification programmée des valeurs ne le déclenchent pas. Mais le déclenchement de l'événement de changement déclenchera la validation. Par exemple, avec jQuery:

$('#formField1, #formField2').trigger('change');
1
Jacob Mouka

J'ai fait quelque chose pour que cela fonctionne.

<form name="form" name="plantRegistrationForm">
  <div ng-class="{ 'has-error': (form.$submitted || form.headerName.$touched) && form.headerName.$invalid }">
    <div class="col-md-3">
      <div class="label-color">HEADER NAME 
        <span class="red"><strong>*</strong></span></div>
    </div>
    <div class="col-md-9">
      <input type="text" name="headerName" id="headerName" 
             ng-model="header.headerName" 
             maxlength="100" 
             class="form-control" required>
      <div ng-show="form.$submitted || form.headerName.$touched">
        <span ng-show="form.headerName.$invalid" 
              class="label-color validation-message">Header Name is required</span>
      </div>
    </div>
  </div>

  <button ng-click="addHeader(form, header)" 
          type="button" 
          class="btn btn-default pull-right">Add Header
  </button>

</form>

Dans votre contrôleur, vous pouvez faire;

addHeader(form, header){
        let self = this;
        form.$submitted = true;
        ... 
    }

Vous avez aussi besoin de css;

.label-color {
            color: $gray-color;
        }
.has-error {
       .label-color {
            color: rgb(221, 25, 29);
        }
        .select2-choice.ui-select-match.select2-default {
            border-color: #e84e40;
        }
    }
.validation-message {
       font-size: 0.875em;
    }
    .max-width {
        width: 100%;
        min-width: 100%;
    }
0
Mahib

J'aime la cette approche dans la validation de la manipulation sur un clic de bouton. 

  1. Il n'y a pas besoin d'invoquer quoi que ce soit du contrôleur, 

  2. tout est traité avec une directive.

sur github

0
Sathish Naga

Vous pouvez essayer ceci:

// The controller

$scope.submitForm = function(form){
   		//Force the field validation
   		angular.forEach(form, function(obj){
   			if(angular.isObject(obj) && angular.isDefined(obj.$setDirty))
   			{ 
   				obj.$setDirty();
   			}
   		})
        
        if (form.$valid){
		
			$scope.myResource.$save(function(data){
		     	//....
			});
		}
}
<!-- FORM -->

  <form name="myForm"  role="form" novalidate="novalidate">
<!-- FORM GROUP to field 1 -->
  <div class="form-group" ng-class="{ 'has-error' : myForm.field1.$invalid && myForm.field1.$dirty }">
      <label for="field1">My field 1</label>
        <span class="nullable"> 
        <select name="field1" ng-model="myresource.field1" ng-options="list.id as list.name for list in listofall"
          class="form-control input-sm" required>
            <option value="">Select One</option>
        </select>
        </span>
        <div ng-if="myForm.field1.$dirty" ng-messages="myForm.field1.$error" ng-messages-include="mymessages"></div>
  </div>
    
<!-- FORM GROUP to field 2 -->
  <div class="form-group" ng-class="{ 'has-error' : myForm.field2.$invalid && myForm.field2.$dirty }">
    <label class="control-label labelsmall" for="field2">field2</label> 
      <input name="field2" min="1" placeholder="" ng-model="myresource.field2" type="number" 
      class="form-control input-sm" required>
    <div ng-if="myForm.field2.$dirty" ng-messages="myForm.field2.$error" ng-messages-include="mymessages"></div>
  </div>

  </form>

<!-- ... -->
<button type="submit" ng-click="submitForm(myForm)">Send</button>

0
Vinicius Trindade