web-dev-qa-db-fra.com

Fonctionnalité de type ngChange pour l'ensemble du formulaire

Je voudrais faire un équivalent de ng-change pour le formulaire entier chaque fois qu'il y a un changement dans l'un de ses champs de saisie.

Je sais que depuis AngularJS 1.3, j'ai l'option anti-rebond, mais elle ne s'applique qu'à une seule entrée.

Je recherche une fonctionnalité "debounce"/"on change" qui s'appliquera à l'ensemble du formulaire.

38
chenop

Il n'y a pas de méthode intégrée pour faire ng-change pour un formulaire.

Il n'est peut-être même pas nécessaire, car si vous avez correctement organisé votre modèle de vue, vos entrées de formulaire sont probablement liées à une certaine propriété exposée par l'étendue:

$scope.formData = {};

et dans la vue:

<form name="form1">
  <input ng-model="formData.a">
  <input ng-model="formData.b">
</form>

Ensuite, vous pouvez regarder en profondeur (avec $watch) pour les changements de modèle (et appliquez l'option anti-rebond aux éléments dont vous avez besoin):

$scope.$watch("formData", function(){
  console.log("something has changed");
}, true);

Ensuite, le problème est , bien sûr, qu'il s'agit d'une surveillance approfondie et coûteuse. En outre, il réagit non seulement aux modifications du formulaire, mais également à une modification de formData de n'importe quelle source.

Ainsi, comme alternative, vous pouvez créer votre propre directive pour compléter le formulaire et réagir aux événements de modification du formulaire.

.directive("formOnChange", function($parse){
  return {
    require: "form",
    link: function(scope, element, attrs){
       var cb = $parse(attrs.formOnChange);
       element.on("change", function(){
          cb(scope);
       });
    }
  }
});

et l'utilisation est:

<form name="form1" form-on-change="doSomething()">
  <input ng-model="formData.a">
  <input ng-model="formData.b">
</form>

plunker pour illustration.

Notez que l'événement "change" est déclenché uniquement sur flou pour une entrée de texte, selon documentation jQuery:

L'événement change est envoyé à un élément lorsque sa valeur change. Cet événement est limité à <input> éléments, <textarea> cases et <select> éléments. Pour les zones de sélection, les cases à cocher et les boutons radio, l'événement est déclenché immédiatement lorsque l'utilisateur effectue une sélection avec la souris, mais pour les autres types d'élément, l'événement est différé jusqu'à ce que l'élément perd le focus.

57
New Dev

une façon "hacky" de le faire est de définir un observateur sur le formulaire sale, valide en fonction de vos besoins, vous pouvez faire quelque chose comme

   $scope.$watch('form.$dirty',function(v){
         if(!v){return}
         form.$setPristine()
         /*do something here*/
    })

cela s'exécutera chaque fois que le formulaire sera modifié, si vous ne souhaitez exécuter votre code que sur un formulaire modifié valide, vous pouvez le faire

       if(!v || form.$invalid){return}

et si vous ne voulez exécuter votre code que lorsque le formulaire passe à l'état $ valid, il vous suffit de configurer votre observateur pour 'form. $ valid'

si vous n'aimez pas polluer votre portée avec les observateurs, vous pouvez toujours créer une directive autour du formulaire qui expose un événement api en cours de modification et prend en charge en interne l'observateur

8
Dayan Moreno Leon

Selon le commentaire d'Eric Soyke, vous pouvez brancher la vérification du changement de formulaire sur l'événement de saisie.

De cette façon, vous pouvez simplement utiliser la directive intégrée ng-keyup:

<form name="form1" ng-keyup="doSomething()">
7
Lorenzo Meriggi

ok, super super réponse tardive ... mais ça marche plutôt bien

// html
<form name="$ctrl.form">...</form>

// controller
function $postLink() {
    ctrl.form.$$element.on('change', function () {
        console.log('fired');
    });
}
1
Eydrian