ngModel格式化程序和解析器


103

我以不同的形式发布了相同的问题,但没有人回答。我没有清楚了解angular js中Formatter和Parsers的功能。

根据定义,格式化程序和解析器都与我相似。也许我错了,因为我是这个angularjs的新手。

格式器定义

每当模型值更改时,作为管道执行的函数数组。依次调用每个函数,将值传递给下一个。用于格式化/转换值以在控件和验证中显示。

解析器定义

每当控件从DOM读取值时,作为管道执行的函数数组。依次调用每个函数,将值传递给下一个。用于清除/转换值以及进行验证。为了进行验证,解析器应使用$ setValidity()更新有效性状态,并为无效值返回undefined。

请通过一个简单的示例帮助我了解这两个功能。两者的简单说明将不胜感激。


2
格式化程序会修改模型的显示值,例如显示(123) 123-1234电话号码。解析器每次更改数据时都会读取数据,通常用于设置输入的$ valid状态。该文档有两个示例。
km6zla 2014年

Answers:


155

这个问题在一个相关的问题中得到了很好的介绍:如何在AngularJS中进行双向过滤?

总结一下:

  • 格式化程序更改模型值在视图中的显示方式。
  • 解析器更改视图值在模型中的保存方式。

这是一个简单的示例,以NgModelController api文档中的示例为基础

  //format text going to user (model to view)
  ngModel.$formatters.push(function(value) {
    return value.toUpperCase();
  });

  //format text from the user (view to model)
  ngModel.$parsers.push(function(value) {
    return value.toLowerCase();
  });

您可以看到它的运行情况:http : //plnkr.co/UQ5q5FxyBzIeEjRYYVGX?plnkr=legacy

<input type="button" value="set to 'misko'" ng-click="data.name='misko'"/>
<input type="button" value="set to 'MISKO'" ng-click="data.name='MISKO'"/>
<input changecase ng-model="data.name" />

在(查看模型)中键入名称时,您将看到模型始终是小写字母。但是,当您单击按钮并以编程方式更改名称(要查看的模型)时,输入字段始终为大写。


2
有什么方法可以根据用户类型设置此更改?您说“以编程方式”,但是我试图使$ viewValue在用户输入内容时进行格式化,例如信用卡号码格式
iamyojimbo

3
@SavvasNicholas如果我没记错的话,您可以使用ngModel.$setViewValue(transformedInput);它来设置它,并ngModel.$render();从$ parsers函数中渲染它。
Jacob Ensor

就我而言,$formatters做什么将立即由恢复$validators。;(
Mikhail Batcer

1
仅供参考,不再有被引用的pl客
克里斯·布朗

1
我注意到格式化程序仅在您按下按钮时才起作用,而不是在字段中键入名称
时才起作用

6

格式化程序和解析器的另一种用法是,当您想以UTC时间存储日期并在输入时以本地时间显示日期时,我为此创建了以下datepicker指令和utcToLocal过滤器。

(function () {
    'use strict';

    angular
        .module('app')
        .directive('datepicker', Directive);

    function Directive($filter) {
        return {
            require: 'ngModel',
            link: function (scope, element, attr, ngModel) {
                element.addClass('datepicker');
                element.pickadate({ format: 'dd/mm/yyyy', editable: true });

                // convert utc date to local for display
                ngModel.$formatters.push(function (utcDate) {
                    if (!utcDate)
                        return;

                    return $filter('utcToLocal')(utcDate, 'dd/MM/yyyy');
                });

                // convert local date to utc for storage
                ngModel.$parsers.push(function (localDate) {
                    if (!localDate)
                        return;

                    return moment(localDate, 'DD/MM/YYYY').utc().toISOString();
                });
            }
        };
    }
})();

它使用此utcToLocal过滤器来确保输入日期的格式正确,然后再转换为本地时间。

(function () {
    'use strict';

    angular
        .module('app')
        .filter('utcToLocal', Filter);

    function Filter($filter) {
        return function (utcDateString, format) {
            if (!utcDateString) {
                return;
            }

            // append 'Z' to the date string to indicate UTC time if the timezone isn't already specified
            if (utcDateString.indexOf('Z') === -1 && utcDateString.indexOf('+') === -1) {
                utcDateString += 'Z';
            }

            return $filter('date')(utcDateString, format);
        };
    }
})();

moment.js用于将本地日期转换为utc日期。

pickadate.js是使用的datepicker插件

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.