在输入元素中使用 angularjs 过滤器

Posted

技术标签:

【中文标题】在输入元素中使用 angularjs 过滤器【英文标题】:Using angularjs filter in input element 【发布时间】:2013-02-26 21:27:35 【问题描述】:

我希望我没有遗漏 doco 中的任何明显内容,如果我有,我相信有人会提供帮助。

我正在使用 asp.net webapi 返回一个带有日期字段的 DTO。这些是使用 JSON.Net 序列化的(格式为“2013-03-11T12:37:38.693”)。

我想在 INPUT 元素中使用过滤器,这可能吗?或者我应该创建一个新的过滤器或指令来完成此操作?

// this just displays the text value
<input ui-datetime type="text" data-ng-model="entity.date" /> 
// this doesn't work at all
<input ui-datetime type="text" data-ng-model="entity.date|date:'dd/MM/yyyy HH:mm:ss a'" /> 
// this works fine
entity.date|date:'dd/MM/yyyy HH:mm:ss a'

我缺少什么快捷方式吗?

【问题讨论】:

【参考方案1】:

简而言之:如果您希望数据在视图和模型中具有不同的表示形式,则需要一个指令,您可以将其视为双向过滤器

你的指令看起来像

angular.module('myApp').directive('myDirective', function() 
  return 
    require: 'ngModel',
    link: function(scope, element, attrs, ngModelController) 
      ngModelController.$parsers.push(function(data) 
        //convert data from view format to model format
        return data; //converted
      );

      ngModelController.$formatters.push(function(data) 
        //convert data from model format to view format
        return data; //converted
      );
    
  
);

html

<input my-directive type="text" data-ng-model="entity.date" /> 

这是一个有效的jsFiddle 示例。

【讨论】:

看起来不错,但您将如何应用它?具体来说,如何指定在格式化中使用的过滤器? @PaulTaylor 将此指令限制为仅“属性”,并在输入字段上使用该属性(类似于您编写 &lt;input ng-model="foo"&gt; 的方式。 还可以查看this answer 以获得更完整的示例。 JSFiddle 上的工作示例? 谢谢!您的示例对我的解决方案唯一缺少的是观察模型的更改并重新运行格式化程序。我不明白如何使用 AngularJS 轻松实现这一点,我不得不强制更新元素:scope.$watch(attrs.ngModel, function(value) element.val( $filter('number')(value, 0) ); );【参考方案2】:

在输入字段和模型中使用不同的值违背了 ng-model 的本质。所以我建议你采取最简单的方法,在控制器中应用你的过滤器,使用一个单独的变量来格式化日期,并使用观察者来保持格式化日期和原始日期同步:

HTML:

<input ui-datetime type="text" data-ng-model="formattedDate" />

JS:

app.controller('AppController', function($scope, $filter)

  $scope.$watch('entity.date', function(unformattedDate)
    $scope.formattedDate = $filter('date')(unformattedDate, 'dd/MM/yyyy HH:mm:ss a');
  );

  $scope.$watch('formattedDate', function(formattedDate)
    $scope.entity.date = $filter('date')(formattedDate, 'yyy/MM/dd');
  );

  $scope.entity = date: '2012/12/28';

);

【讨论】:

我相信创建一个新指令来满足要求是一个更清洁的解决方案。如果我正确理解了 OP 的问题。 你是对的。它更干净。我只是想给@leon 一个选项,以防他/她对自定义指令不太满意。 谢谢大家,两个答案都很感谢,因为学习替代方法很棒。 -1,两个变量+看是支持地狱。想象一个有几十个变量的范围(保险计算器等)【参考方案3】:

如果您的输入仅显示数据

如果您确实需要输入来简单地显示一些信息,并且它是一些其他元素更改 Angular 模型,您可以进行更轻松的更改。

与其编写新指令,不如简单地不要使用ng-model 并使用好旧的value

所以而不是:

<input data-ng-model=entity.date|date:'dd/MM/yyyy HH:mm:ss'" /> 

这样就可以了:

<input value="entity.date|date:'dd/MM/yyyy HH:mm:ss'" /> 

而且像魅力一样工作:)

【讨论】:

【参考方案4】:

格式化数字的完整示例,每 3 个字符插入空格,从末尾开始:

'use strict'
String::reverse = ->
  @split('').reverse().join('')

app = angular.module('app', [])
app.directive 'intersperse', ->
  require: 'ngModel'
  link: (scope, element, attrs, modelCtrl) ->
    modelCtrl.$formatters.push (input) ->
      return unless input?
      input = input.toString()
      input.reverse().replace(/(.3)/g, '$1 ').reverse()
    modelCtrl.$parsers.push (input) ->
      return unless input?
      input.replace(/\s/g, '')

用法:

<input ng-model="price" intersperse/>

Plunkr 示例:http://plnkr.co/edit/qo0h9z

【讨论】:

modelCtrl.$parsers(or formatters).push 到底是做什么的? @Vincent,它向格式化程序数组添加了一个函数,当需要显示模型中的值时调用该函数。将 $formatters 数组视为一个填充有函数的管道,其中每个函数都被调用,结果通过管道进一步传递。调用所有函数后,将显示最终结果。 $parsers 是类似的东西,但用于写入模型。 我不认为这真的有效,你有 plunker 或类似的吗? 不错!唯一的问题是它在任何长度为 3 的倍数的数字之前添加一个空格,正确的方法是仅在长度是 3 的倍数并且后面有另一个数字时才添加空格。当您的语言环境没有将数字分隔符定义为点 (.) 时,这看起来不是问题,它看起来像这样:.999.999 PS.: 使用$filter('number'); 似乎是一种更好的方法,它通过$locale 服务加载格式,您可以使用new RegExp("\\"+$locale.NUMBER_FORMATS.GROUP_SEP, 'g'); 将值反转为模型。 .【参考方案5】:

Angular 已内置 date format 功能,但要将其应用于您最终希望获取原始(未格式化)日期的输入,您需要创建一个自定义 directive。

指令示例:

(function () 
    'use strict';

    angular.module('myApp').directive('utcDate', ['$filter', function ($filter) 
        return 
            restrict: 'A', //restricting to (A)ttributes
            require: 'ngModel',
            link: function (scope, elem, attrs, model) 
                if (!model) return;

                var format = 'MM/dd/yyyy h:mm:ss a';
                var timezone = 'UTC';

                //format the date for display
                model.$formatters.push(function (value) 
                    //using built-in date filter
                    return $filter('date')(value, format, timezone);
                );

                //remove formatting to get raw date value
                model.$parsers.push(function (value) 
                    var date = Date.parse(value);
                    return !isNaN(date) ? new Date(date) : undefined;
                );
            
        ;
    ]);
)();

然后应用它:

<input type="text" ng-model="$ctrl.DateField" utc-date />

【讨论】:

【参考方案6】:

您不需要从零开始创建新过滤器,因为 Angular 已经为日期类型提供了内置过滤器。 http://docs.angularjs.org/api/ng.filter:date

我相信这正是您所需要的。

【讨论】:

-1,OP 询问使用带有ngModel 的过滤器的具体问题,这与创建新过滤器完全不同。

以上是关于在输入元素中使用 angularjs 过滤器的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS 过滤器(filter)

angularjs filter详解

AngularJS - 如何在我输入时在文本框上应用货币过滤器?

使用分页 AngularJs 进行复合过滤

angularjs 判断字符串是不是是数字格式

angularjs随笔01 数据双向绑定理解 自定义过滤器 时钟更新列子