Angular 中的货币格式化指令 [英] Money formatting directive in Angular

查看:49
本文介绍了Angular 中的货币格式化指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个指令来过滤货币字段,因此用户只需要键入并且隐含小数.

I need a directive for filtering a field for currency, so a user just needs to type and the decimal is implied.

需求:

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

在用户键入时从百分之一开始.所以他们会输入4"看到0.04",输入42"看到0.42",输入298023看到2980.23"

  1. 字段必须是数字
  2. 必须允许否定-
  3. 允许 0.00 作为数字输入
  4. 最好使用 type="number" 但 "type=text" 也可以
  5. 您应该能够将该字段清除为空.

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

The ng-currency filter does not fulfill these requirements as is. Please see behaviour in plunkers to see what I mean.

我的 First Plunker 有 `input = text' 并允许负数.一个问题是您不能输入负数作为第一个数字.当您清除该字段时,它会返回到0.00",但应该完全清除.

My First Plunker has `input = text' and allows negative numbers. One problem is that you cannot type a negative as the very first number. When you clear the field, it returns to '0.00' but it should completely clear.

   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 Plunker 具有 input = text 并允许对于负输入.像第一个 plunker 一样,它不允许第一个字符为负数,只有在输入数字之后.第二个是它从十分位而不是百分之一开始.(如果您输入3",您应该会看到0.03",但这里显示的是0.3")

My Second Plunker has input = text and allows for negative input. Like the first plunker, it won't allow a negative as the first character, only after numbers are typed. The second is that it starts at the tenths place instead of the hundredths. (if you type '3' you should see '0.03' but here it shows '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);
        }
    };
}]);

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

How can I reconcile these solutions or tailor one to meet the requirements? I want to avoid extra libraries or add-ons. I have been told that the best approach would be to study the source for the currency filter, and recreate that filter with the additional requirements.I would love to do this, but I really don't have the skills for it right now. These two directives are what I have.

推荐答案

.:: 更新答案 - 7 月 14 日 ::.

<小时>

检查这个简单的指令:

.:: Updated Answer - July 14 ::.


Check this simple directive:

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)(?=(ddd)+(?!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 日) 中现场观看>

See it live in this PLUNKER (July 14)

这篇关于Angular 中的货币格式化指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆