11

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

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

使用 ng-model 进行简单输入

<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/

谢谢你的帮助。

4

3 回答 3

10

我无法让 $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);
            };

        }
    };
})
于 2013-09-22T12:33:19.240 回答
9

更新模型$formatters时调用 get以格式化要呈现给用户的值。反之亦然,即将视图字符串中的值转换为真实模型,例如数字。$parsers

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

于 2013-09-22T10:42:40.533 回答
0

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

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

于 2013-09-22T07:22:15.057 回答