带有ng-model的输入框中的Angularjs货币格式:如何让$formatters在每个输入上触发

Angularjs currency format in input box with ng-model: how to get $formatters to fire on each input

本文关键字:输入 formatters ng-model Angularjs 货币 带有 格式      更新时间:2023-09-26

我到处搜索过这个。每个有答案的堆栈溢出,它实际上不起作用。与包括文档在内的任何示例或谷歌组示例相同。

看起来很简单。我希望在用户按下的每个键的输入上调用一个函数。

使用 ng 模型进行简单输入

<input class="form-control" ng-model="model.thisisnotfun" formatter type="text" required>

根据我读到的一切。 $formatters应该将值从模型更新到调用 $formatters 数组中任何函数的视图。当我在输入框中键入时,它们永远不会被调用。

.directive('formatter', function ($filter, $parse) {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            ngModel.$formatters.push(
                function (value) {
                    console.log('this only gets called on page load');
                }
            );
        }
    };
})

我知道有很多自定义方法可以做到这一点,我已经这样做了。我不需要变通方法,我只想知道如何正确使用$formatters来"格式化"视图数据。

非常简单的 JSFIDDLE http://jsfiddle.net/fh7sB/4/

感谢您的任何帮助。

我无法让$formatters函数像我想要的那样工作。我也找不到我在任何地方寻找的单一示例,所以我将发布我的答案,以防有人需要它。

这是一个使用 ng-model 在输入框中格式化美国货币的指令

    .directive('uiCurrency', function ($filter, $parse) {
    return {
        require: 'ngModel',
        restrict: 'A',
        link: function (scope, element, attrs, ngModel) {
            function parse(viewValue, noRender) {
                if (!viewValue)
                    return viewValue;
                // strips all non digits leaving periods.
                var clean = viewValue.toString().replace(/[^0-9.]+/g, '').replace(/'.{2,}/, '.');
                // case for users entering multiple periods throughout the number
                var dotSplit = clean.split('.');
                if (dotSplit.length > 2) {
                    clean = dotSplit[0] + '.' + dotSplit[1].slice(0, 2);
                } else if (dotSplit.length == 2) {
                    clean = dotSplit[0] + '.' + dotSplit[1].slice(0, 2);
                }
                if (!noRender)
                    ngModel.$render();
                return clean;
            }
            ngModel.$parsers.unshift(parse);
            ngModel.$render = function() {
                console.log('viewValue', ngModel.$viewValue);
                console.log('modelValue', ngModel.$modelValue);
                var clean = parse(ngModel.$viewValue, true);
                if (!clean)
                    return;
                var currencyValue,
                    dotSplit = clean.split('.');
                // todo: refactor, this is ugly
                if (clean[clean.length-1] === '.') {
                     currencyValue = '$' + $filter('number')(parseFloat(clean)) + '.';
                } else if (clean.indexOf('.') != -1 && dotSplit[dotSplit.length - 1].length == 1) {
                    currencyValue = '$' + $filter('number')(parseFloat(clean), 1);
                } else if (clean.indexOf('.') != -1 && dotSplit[dotSplit.length - 1].length == 1) {
                    currencyValue = '$' + $filter('number')(parseFloat(clean), 2);
                } else {
                     currencyValue = '$' + $filter('number')(parseFloat(clean));
                }
                element.val(currencyValue);
            };
        }
    };
})
更新

模型时调用$formatters,以便格式化要呈现给用户的值。$parsers做相反的事情,即将值从视图字符串转换为真实模型,例如数字。

在这里的分叉小提琴中:http://jsfiddle.net/9tuCz/按下按钮;它会改变模型并再次触发$formatters

确保你

实际上从函数中返回了一个有效的值。

可能发生的情况是,由于解析器每次都返回相同的值,格式化程序假定格式化的输出也不会更改,因此它会跳过调用。