Angular中的Money格式指令

时间:2016-06-27 20:15:09

标签: javascript angularjs angularjs-directive format currency

我需要一个过滤货币字段的指令,因此用户只需要输入并隐含小数。

需要:

  1. 将十进制字段格式化为用户类型 -
  2. 在用户输入时从百分位开始。所以他们输入“4”并输入“0.04”,输入“42”并看“0.42”,输入298023并看“2980.23”

    1. 字段必须是数字
    2. 必须允许否定-
    3. 允许0.00作为数字输入
    4. 理想情况下会使用type =“number”,但“type = text”是可以的
    5. 您应该能够清除该字段为空。
    6. ng-currency过滤器不能满足这些要求。请看看掠夺者的行为,看看我的意思。

      我的First Plunker有`input = text'并允许负数。一个问题是你不能输入负数作为第一个数字。清除该字段后,它将返回“0.00”,但应完全清除。

         app.directive('format', ['$filter', function ($filter) {
       return {
                  require: 'ngModel', //there must be ng-model in the html
                  link: function (scope, elem, attr, ctrl) {
                      if (!ctrl) return;
      
                      ctrl.$parsers.unshift(function (viewValue, modelValue) {
                          var plainNumber = viewValue.replace(/[^-+0-9]/g,'');
                          var newVal = plainNumber.charAt(plainNumber.length-1);
                          var positive = plainNumber.charAt(0) != '-';
                          if(isNaN(plainNumber.charAt(plainNumber.length-1))){
                            plainNumber = plainNumber.substr(0,plainNumber.length-1)
                          }
                          //use angular internal 'number' filter
                          plainNumber = $filter('number')(plainNumber / 100, 2).replace(/,/g, '');
                          if(positive && newVal == '-'){
                            plainNumber = '-' + plainNumber;
                          }
                          else if(!positive && newVal == '+'){
                            plainNumber = plainNumber.substr(1);
                          }
                          plainNumber.replace('.', ',');
      
                          //update the $viewValue
                          ctrl.$setViewValue(plainNumber);
                          //reflect on the DOM element
                          ctrl.$render();
                          //return the modified value to next parser
                          return plainNumber;
                      });
                  }
              };
      
      }]);
      

      我的Second Plunkerinput = text并允许输入否定值。与第一个plunker一样,只有在键入数字后才会允许负数作为第一个字符。第二是它从十分之一开始,而不是百分之一。 (如果你输入'3'你会看到'0.03',但这里显示'0.3')

      app.directive('inputRestrictor', [function() {
          return {
              restrict: 'A',
              require: 'ngModel',
              link: function(scope, element, attr, ngModelCtrl) {
                  var pattern = /[^.0-9+-]/g;
      
                  function fromUser(text) {
                      if (!text)
                      return text;
      
                      var rep = /[+]/g;
                      var rem = /[-]/g;
                      rep.exec(text);
                      rem.exec(text);
      
                      var indexp = rep.lastIndex;
                      var indexm = rem.lastIndex;
                      text = text.replace(/[+.-]/g, '');
                      if (indexp > 0 || indexm > 0) {
                          if (indexp > indexm) text = "+" + text; // plus sign?
                          else text = "-" + text;
                      }
      
                      var transformedInput = text.replace(pattern, '');
                      transformedInput = transformedInput.replace(/([0-9]{1,2}$)/, ".$1")
                      ngModelCtrl.$setViewValue(transformedInput);
                      ngModelCtrl.$render();
                      return transformedInput;
                  }
      
                  ngModelCtrl.$parsers.push(fromUser);
              }
          };
      }]);
      

      如何协调这些解决方案或量身定制以满足要求?我想避免额外的库或附加组件。有人告诉我,最好的办法是研究货币过滤器的来源,然后用额外的要求重新创建过滤器。我很乐意这样做,但我现在真的没有这方面的技能。这两个指令就是我所拥有的。

3 个答案:

答案 0 :(得分:8)

。::更新的答案 - 7月14日::。

检查这个简单的指令:

app.directive('price', [function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            attrs.$set('ngTrim', "false");

            var formatter = function(str, isNum) {
                str = String( Number(str || 0) / (isNum?1:100) );
                str = (str=='0'?'0.0':str).split('.');
                str[1] = str[1] || '0';
                return str[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') + '.' + (str[1].length==1?str[1]+'0':str[1]);
            }
            var updateView = function(val) {
                scope.$applyAsync(function () {
                    ngModel.$setViewValue(val || '');
                    ngModel.$render();
                });
            }
            var parseNumber = function(val) {
                var modelString = formatter(ngModel.$modelValue, true);
                var sign = {
                    pos: /[+]/.test(val),
                    neg: /[-]/.test(val)
                }
                sign.has = sign.pos || sign.neg;
                sign.both = sign.pos && sign.neg;

                if (!val || sign.has && val.length==1 || ngModel.$modelValue && Number(val)===0) {
                    var newVal = (!val || ngModel.$modelValue && Number()===0?'':val);
                    if (ngModel.$modelValue !== newVal)
                        updateView(newVal);

                    return '';
                }
                else {
                    var valString = String(val || '');
                    var newSign = (sign.both && ngModel.$modelValue>=0 || !sign.both && sign.neg?'-':'');
                    var newVal = valString.replace(/[^0-9]/g,'');
                    var viewVal = newSign + formatter(angular.copy(newVal));

                    if (modelString !== valString)
                        updateView(viewVal);

                    return (Number(newSign + newVal) / 100) || 0;
                }
            }
            var formatNumber = function(val) {
                if (val) {
                    var str = String(val).split('.');
                    str[1] = str[1] || '0';
                    val = str[0] + '.' + (str[1].length==1?str[1]+'0':str[1]);
                }
                return parseNumber(val);
            }

            ngModel.$parsers.push(parseNumber);
            ngModel.$formatters.push(formatNumber);
        }
    };
}]);

并像这样使用它:

<input type="text" ng-model="number" price >

PLUNKER(7月14日)

中查看

答案 1 :(得分:3)

我认为这可以完全满足您的要求

https://github.com/FCSAmerica/angular-fcsa-number

您可以限制输入,该输入仅允许带有小数的数字,默认为角度输入验证或使用字符代码。

答案 2 :(得分:1)

Angular Numeric

Angular Numeric是一个复杂的指令,它实现了一个完整的数字输入字段。

使用起来非常简单 - 但功能强大。

<input numeric min="-20" max="100" decimals="3" />
  

检查最小值和最大值。当价值低于   minumum将值设置为最小值。当值超过时   最大值,该值设置为最大值。

     

格式化模糊事件;千分隔符和小数   基于当前的Angular语言环境。

     

可以设置小数位数。

https://www.npmjs.com/package/angular-numeric-directive