【问题标题】:Using angularjs filter in input element在输入元素中使用 angularjs 过滤器
【发布时间】: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'}}

我缺少什么快捷方式吗?

【问题讨论】:

    标签: angularjs asp.net-web-api angularjs-directive


    【解决方案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 的过滤器的具体问题,这与创建新过滤器完全不同。
        猜你喜欢
        • 2014-09-12
        • 1970-01-01
        • 2016-10-20
        • 2016-03-03
        • 1970-01-01
        • 1970-01-01
        • 2015-07-18
        • 2015-07-18
        • 2018-10-03
        相关资源
        最近更新 更多