AngularJS comment forcer une entrée à nouveau rendu sur le flou

J'ai quelques code de validation personnalisé, qui comprend un $formateur. (J'ai monnaie banque en pence pour l'exactitude, mais l'affichage dans les livres.pence.)

Si l'utilisateur tape '10' dans l'entrée (qui est une valeur valide), l'entrée reste l'affichage de '10' après ils passer au champ suivant.

Je voudrais qu'il affiche à 10.00 pour des raisons de cohérence.

Si le modèle a changé la valeur de 1000, puis le formateur rendrait le champ d'affichage '10.00'.

Je voudrais le formateur à exécuter sur le champ.blur() (tant que l'entrée est valide).

Mon problème est que si je change la valeur de modèle de 10 à 10, il n'y a naturellement pas de changement, et donc le champ n'est pas un nouveau rendu.

code:

var CURRENCY_REGEXP = /^\-?\d+(\.?\d?\d?)?$/;
app.directive('currency', function() {
  return {
    require: 'ngModel',
    link: function(scope, elm, attrs, ctrl) {
      ctrl.$parsers.unshift(function(viewValue) {
        if (CURRENCY_REGEXP.test(viewValue)) {
          //it is valid
          ctrl.$setValidity('currency', true);
          console.log("valid");
          return viewValue * 100;
        } else if (viewValue === '') {
          return 0;
        } else {
          //it is invalid, return undefined (no model update)
          ctrl.$setValidity('currency', false);
          console.log("invalid");
          return undefined;
        }
      });
      ctrl.$formatters.push(function(modelValue) {
         if (modelValue === 0) { //we're using integer pence, so this is safe
             return '';
         }
         return (modelValue / 100).toFixed(2); 
      });
    }
  };
});

P. S. Cela n'a rien à voir avec Angulaire intégrée de "monnaie".


Mise à jour: j'ai ajouté un "renderOnBlur" directive, comme par Andy réponse. Elle est appelée, mais l'appel de la méthode render de ne pas re-rendre l'entrée. c'est à dire '10' reste '10', plutôt que de changer de '10.00', comme souhaité.

(Lorsque le modèle de changement de la valeur dans ces domaines, ils sont correctement rendus avec 2 décimales.)

La page qui Andy mentionne http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController dit que vous avez à mettre en œuvre $render vous-même. Cela semble bizarre, ainsi que les entrées sont déjà rendus correctement lorsque le modèle de changement de valeur.

app.directive('renderOnBlur', function() {
    return {
        require: 'ngModel',
        restrict: 'A',
        link: function(scope, elm, attrs, ctrl) {
            elm.bind('blur', function() {
                console.log('rendering ctrl', ctrl);
                ctrl.$render();
            });
        }
    };  
});

P. S. je n'ai aucune idée de ce que restrict: 'A', t - il est vrai-cargo culte de la programmation au pire. Le require: 'ngModel', semble nécessaire pour remplir le ctrl paramètre.


Inspiré par la réponse de @Dan monsieur le Doyen, je l'ai réécrit comme:

app.directive('renderOnBlur', function() {
    return {
        require: 'ngModel',
        restrict: 'A',
        link: function(scope, elm, attrs, ctrl) {
            elm.bind('blur', function() {
                var viewValue = ctrl.$modelValue;
                for (var i in ctrl.$formatters) {
                    viewValue = ctrl.$formatters[i](viewValue);
                }
                ctrl.$viewValue = viewValue;
                ctrl.$render();
            });
        }
    };  
});

Cela a l'avantage d'être générique pour tout $formateur, plutôt que de répéter le formateur de code que Dan réponse.

  • 10.00 === 10 //true; .00 ne pas dire n'importe quoi sur javascript
  • veuillez voir le commentaire sous votre réponse. Vous avez une expérience de AngularJS?
  • restreindre: "A" signifie que vous ne souhaitez autoriser la directive être utilisée comme un attribut <input rendu-sur-flou>, il existe 4 différents types de restrictions que les autres sont 'E'lement <render-sur-flou>, 'C'lass <input class=" render-sur-flou " > et Co SUIS'ment (qui est moins utilisé - voir doc). Vous pouvez avoir plusieurs limiter: 'EAC'
  • c'est un bon fil, ce qui rend un jsfiddle de l'ensemble de directives utilisées dans la question sera d'aider les autres à lire rapidement autour et en savoir plus. La plupart d'entre eux viennent ici pendant la navigation sur le web et la recherche d'une sorte de ng la compréhension.
  • Avez-vous un exemple d'un karma?) test de votre directive?
  • (Désolé, juste de l'apprentissage Angulaire...) Afin que votre vue doit être quelque chose comme <input currency render-on-blur>, droit? I. e.: les deux "monnaie" et "rendre-sur-flou" attributs doivent être spécifiés?
  • Sur $formatters, l'angle de la documentation dit "Les fonctions sont appelées dans le sens inverse de la matrice de commande, chaque passage de la valeur à la prochaine." La directive exige que les dans le bon ordre. Juste pensé que je note cela pour personne d'autre, que ce morceau m'lorsque l'on travaille avec plusieurs formateurs.
  • Votre solution doit être enregistrée comme une réponse trop. J'ai juste utilisé pour résoudre un problème similaire, merci! Vous devriez aussi précise que c'est basé sur angulaire code source

InformationsquelleAutor fadedbee | 2012-07-08