2016-06-27 158 views
12

我需要一个指令来过滤货币的字段,因此用户只需键入并隐含小数。Angular中的Money格式化指令

需求:

  1. 格式小数字段的用户类型 -

开始在百位的用户类型。因此,他们可以键入 “4” 看 “0.04”,输入 “42”,并看到 “0.42”,类型298023和看 “2980.23”

  • 字段必须是数字
  • 必须允许底片-
  • 允许0.00为数字输入
  • 理想的情况下将使用类型=“数字”,而是“类型=文本”是正常
  • 您应该能够清除该字段为空。
  • ng货币筛选器不能按原样满足这些要求。请参阅猛击者的行为以了解我的意思。

    我的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并允许负输入。就像第一个闯入者一样,只有在输入数字后,它才会允许第一个字符为负数。第二个是它从十分之一而不是百分之一开始。 (如果你输入“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

    的角度提供一个内置的货币过滤器:https://docs.angularjs.org/api/ng/filter/currency –

    +0

    @ SSC-hrep3该过滤器是好的,但它不符合作为用户类型添加小数点的要求。这是指令的目的。要明白我的意思,请输入plunker字段,看看会发生什么。 – jenryb

    +1

    嗨,[ng-currency](https://github.com/aguirrel/ng-currency)很有帮助。 – Maher

    回答

    7

    。::更新的答案 - 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日)

    +0

    关闭,但这不会在两位数后添加小数,这应该反映在视图以及模型中。 – jenryb

    +0

    @jenryb你的意思是,你想强制小数点后2位? –

    +0

    是的。看到任何一个强盗的行为,看看我的意思 – jenryb

    3

    我认为这完全可以填补你的要求

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

    可以限制输入,允许只数在默认情况下角输入验证小数或使用字符代码。

    1

    角数字

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

    非常简单易用 - 但功能强大。

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

    上有最小和最大值检查。当该值低于最小值 时,该值被设置为最小值。当值超过最大值 时,该值被设置为最大值。

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

    可以设置小数位数。

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

    +0

    不完全是我在找的东西。我不想在模糊上进行格式化,而应该在用户输入时进行格式化。 – jenryb