Angular, champ d'entrée avec une directive de masque de devise pour le format de monnaie à la volée

j'essaie de créer un masque d'entrée pour un champ de monnaie de L'UE en utilisant http://jquerypriceformat.com/

Jusqu'à présent dans ma directive, l'entrée se montre correctement à l'utilisateur avec le masque appliqué, mais je crois qu'il y a quelque chose qui ne va pas, parce que les valeurs de POST sont envoyées avec un formatage bizarre, totalement différent de ce que nous voyons dans le champ d'entrée.

- je inclure le priceformat.js

<script src="js/jquery.price_format.1.8.min.js"></script>

<input type="text" currency-input ng-model...>

Et sur angulaire:

app.directive('currencyInput', function() {
    return {
      require: '?ngModel',
      link: function($scope, element, attrs, controller) {
        element.priceFormat({
            prefix: '',
            centsSeparator: ',',
            thousandsSeparator: '.'
        });
      }
    };
});
<!-- 2 - input montre la valeur avec le masque correctement, mais sur les données POST (appelé par angular) c'est une valeur différente, qu'est-ce que je manque?

entrée > 2.200,80 | post > 22,0080

Merci

24
demandé sur Antonio Max 2013-10-25 00:40:28

5 réponses

de votre exemple Je ne vois pas que le lien renvoie quelque chose.

je voudrais écrire directive quelque chose comme:

.directive('format', ['$filter', function ($filter) {
    return {
        require: '?ngModel',
        link: function (scope, elem, attrs, ctrl) {
            if (!ctrl) return;


            ctrl.$formatters.unshift(function (a) {
                return $filter(attrs.format)(ctrl.$modelValue)
            });


            ctrl.$parsers.unshift(function (viewValue) {

          elem.priceFormat({
            prefix: '',
            centsSeparator: ',',
            thousandsSeparator: '.'
        });                

                return elem[0].value;
            });
        }
    };
}]);

Démo 1 Tripoter

enter image description here

Si vous voulez sur le début de l'incendie du filtre, utilisez $formatters:

link est:

link: function (scope, elem, attrs, ctrl) {
            if (!ctrl) return;

            var format = {
                    prefix: '',
                    centsSeparator: ',',
                    thousandsSeparator: ''
                };

            ctrl.$parsers.unshift(function (value) {
                elem.priceFormat(format);

                return elem[0].value;
            });

            ctrl.$formatters.unshift(function (value) {
                elem[0].value = ctrl.$modelValue * 100 ;
                elem.priceFormat(format);
                return elem[0].value;
            })
        }

Démo 2 Tripoter

31
répondu Maxim Shoustin 2014-06-25 04:59:07

appuyer sur $parser au controller, et ne mettre à jour la valeur que si elle ne correspond pas à l'entrée en utilisant $setViewValue() et $render().

app.directive('currencyInput', function() {
    return {
      require: '?ngModel',
      link: function($scope, element, attrs, controller) {
        return ctrl.$parsers.push(function(inputValue) {

            ...

            if (result != inputValue) {
                controller.$setViewValue(res);
                controller.$render();
            }
        });
      }
    };
});

voici la logique que j'ai utilisée pour ma directive d'entrée de devises:Tripoter

17
répondu dubilla 2016-02-25 21:31:52

Fin de la partie, mais je crois que cela mérite une autre réponse! J'ai été en utilisant le ng-devise module. C'est absolument fantastique.

3
répondu David Posey 2016-09-02 13:46:46

J'aime L'approche de Dubilla à cause de sa simplicité et de son élégance. J'ai décidé d'ajouter (en crédits) certaines fonctionnalités sur lui pour le rendre assez proche du monde réel de cas d'utilisation.

Je l'ai utilisé sur un projet github pour créer quelques directives financières utiles github.

Notable supplémentaire caractéristiques:

  1. il effectue une vérification rigoureuse des entrées pour donner une réponse valide.
  2. il y a des raccourcis clavier à faire entrée de grands nombres plus rapide.
  3. je montre comment l'intégrer aux mises à jour CSS de bootstrap et ngmodel.
  4. en bonus, j'ai sorti le ngmonel du formulaire comme JSON pour aider les gens à voir comment la validation du formulaire fonctionne en temps réel
function Money() {
    this.notional = 0;
    this.maxValue = 99999999999.9;
    this.maxValueString = "99,999,999,999.9";
    this.maxPrecision = 10;
}
<h1>Currency Formatting directive</h1>

<div class="row">

    <div class="col-md-6">
        <form name="myForm">

            <div class="form-group" ng-class="{'has-error': myForm.notional.$invalid && myForm.notional.$touched}">
                <input type="text" ng-model="myForm.money.notional  " money="money" money-input size="30" required
                       name="notional"
                       class="form-control"
                       placeholder="Enter notional amount"/>

                      <p class="help-block error" ng-show="myForm.notional.$error.required && myForm.notional.$touched">Required</p>



            </div>

            <button ng-disabled="myForm.$invalid" type="submit">SAVE</button>
        </form>
        <h2>Tips</h2>
        <ol>

            <li> Entering 'k' will multiply the amount by one thousand</li>
            <li> Entering 'm' will multiply the amount by one million</li>
            <li> Entering 'b' will multiply the amount by one billion</li>
        </ol>
    </div>
</div>
<p>Form debugger</p>
<pre>
               form = {{ myForm | json }}
    </pre>
1
répondu Nikos 2014-10-10 16:42:49

Voici une façon de gérer cela sans jQuery en utilisant seulement une directive angulaire. Cet exemple ne supporte pas les décimales. Il est facile de le modifier pour le supporter, il suffit de changer le $filter dans le toView() fonction.

à mon avis, c'est une meilleure approche pour résoudre le même problème, car vous pouvez éviter de charger dans jQuery et le plugin monnaie mentionné par l'auteur. La prise en charge Locale de L'Euro doit être supportée par l'utilisation de $locale propriétés, mais j'ai seulement testé ceci pour une utilisation en USD.

(function() {
  var app = angular.module('currencyMask', []);

  // Controller
  app.controller('ctrl', ['$scope', function($scope) {
    $scope.amount = 100000;
  }]);

  // Directive
  app.directive('inputCurrency', ['$locale', '$filter', function($locale, $filter) {

    // For input validation
    var isValid = function(val) {
      return angular.isNumber(val) && !isNaN(val);
    };

    // Helper for creating RegExp's
    var toRegExp = function(val) {
      var escaped = val.replace(/[-\/\^$*+?.()|[\]{}]/g, '\$&');
      return new RegExp(escaped, 'g');
    };

    // Saved to your $scope/model
    var toModel = function(val) {

      // Locale currency support
      var decimal = toRegExp($locale.NUMBER_FORMATS.DECIMAL_SEP);
      var group = toRegExp($locale.NUMBER_FORMATS.GROUP_SEP);
      var currency = toRegExp($locale.NUMBER_FORMATS.CURRENCY_SYM);

      // Strip currency related characters from string
      val = val.replace(decimal, '').replace(group, '').replace(currency, '').trim();

      return parseInt(val, 10);
    };

    // Displayed in the input to users
    var toView = function(val) {
      return $filter('currency')(val, '$', 0);
    };

    // Link to DOM
    var link = function($scope, $element, $attrs, $ngModel) {
      $ngModel.$formatters.push(toView);
      $ngModel.$parsers.push(toModel);
      $ngModel.$validators.currency = isValid;

      $element.on('keyup', function() {
        $ngModel.$viewValue = toView($ngModel.$modelValue);
        $ngModel.$render();
      });
    };

    return {
      restrict: 'A',
      require: 'ngModel',
      link: link
    };
  }]);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>

<div ng-app="currencyMask" ng-controller="ctrl">
	<input input-currency ng-model="amount">
	<p><strong>Amount:</strong> {{ amount }}</p>
</div>
0
répondu Kevin Leary 2017-08-18 19:51:55