Angular 中的货币格式指令

Money formatting directive in Angular

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

需要:

  1. 将十进制字段格式化为用户类型 -

从用户键入的百分之一开始。所以他们会键入“4”并看到“0.04”,键入“42”并看到“0.42”,键入 298023 并看到“2980.23”

  1. 字段必须是数字
  2. 必须允许负数 -
  3. 允许 0.00 作为数字输入
  4. 理想情况下会使用 type="number" 但 "type=text" 没问题
  5. 您应该可以将字段清空。

ng-currency 过滤器无法按原样满足这些要求。请查看 plunkers 中的行为以了解我的意思。

我的 First Plunker 有 `input = text' 并且允许负数。一个问题是您不能将负数作为第一个数字。当您清除该字段时,它 returns 变为 '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}$)/, ".")
                ngModelCtrl.$setViewValue(transformedInput);
                ngModelCtrl.$render();
                return transformedInput;
            }

            ngModelCtrl.$parsers.push(fromUser);
        }
    };
}]);

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

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

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

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

.:: 更新答案 - 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, ',') + '.' + (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 日)

Angular 数值

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

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

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

There are checks on min and max values. When the value falls below the minumum the value is set to the minumum value. When the value exceeds the maxiumum, the value is set to the maximum.

Formatting is done on the blur event; thousand separator and decimal are based on the current Angular locale.

The number of decimals can be set.

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