【问题标题】:angularjs: parsing date inputangularjs:解析日期输入
【发布时间】:2013-09-06 06:07:12
【问题描述】:

我需要一个指令来解析用户输入的日期并验证它。所以我写了以下内容:

myDirectives.directive('myDate', function($filter) {
    'use strict';
    return {
        require:'ngModel',
        restrict:'A',
        link:function (scope, elem, attrs, ctrl) {
            var dateFormat = attrs.myDate ? attrs.myDate : 'shortDate';

            ctrl.$formatters.unshift(function(modelValue) {
                return $filter('date')(modelValue, dateFormat);
            });
            ctrl.$parsers.unshift(function(viewValue) {
                var date = new Date(viewValue);

                if (isNaN(date)) {
                    ctrl.$setValidity('date', false);
                    return undefined;
                } else {
                    var dateString = $filter('date')(date, dateFormat);
                    if (dateString !== viewValue) {
                        ctrl.$setViewValue(dateString);
                    }
                    ctrl.$setValidity('date', true);
                    return date;
                }
            });
        }
    };
});

只有在输入失去焦点后才需要进行解析,所以我使用了另一个指令,我找到了here。问题是

ctrl.$setViewValue(dateString);

不起作用,因为如 angularjs 文档中所述,必须从 DOM 事件处理程序中调用 setViewValue()。我应该怎么做才能反映解析结果?

【问题讨论】:

    标签: javascript angularjs date


    【解决方案1】:

    代替

    ctrl.$setViewValue(dateString);
    

    我需要写

    elem.val(dateString);
    

    问题就解决了。所以,我的指令现在如下所示:

    myDirectives.directive('myDate', function ($filter) {
        'use strict';
        return {
            require: 'ngModel',
            restrict: 'A',
            link: function (scope, elem, attrs, ctrl) {
                var dateFormat = attrs.myDate ? attrs.myDate : 'shortDate';
                ctrl.$formatters.unshift(function (modelValue) {
                    return (modelValue) ? $filter('date')(modelValue, dateFormat) : '';
                });
                ctrl.$parsers.unshift(function (viewValue) {
                    var date = new Date(viewValue);
                    if (isNaN(date)) {
                        ctrl.$setValidity('date', false);
                        return undefined;
                    } else {
                        var dateString = $filter('date')(date, dateFormat);
                        if (dateString !== viewValue) {
                            elem.val(dateString);
                        }
                        ctrl.$setValidity('date', true);
                        return date;
                    }
                });
                elem.unbind('input').unbind('keydown').unbind('change');
                elem.bind('blur', function () {
                    scope.$apply(function () {
                        ctrl.$setViewValue(elem.val()); //this method name is misleading; 
                                                        //it actually sets model value?!
                    });
                });
            }
        };
    });
    

    请注意,当焦点丢失时,我合并了另一个指令中的代码,该指令负责将视图值推送到模型。

    【讨论】:

    • 只是为了评论您在最后一行的评论,$setViewValue() 函数确实做到了:设置视图值,然后继续调用管道中所有已注册的 $parsers 以最终得到模型值,然后在由 ngModel 属性链接的模型中设置。
    【解决方案2】:

    我创建了一个将字符串转换为日期对象的日期解析器。您还可以提供您正在使用的日期格式以及日期区域设置。它返回一个 Date 对象,是否有效取决于输入。

    还有一个实现此解析器的指令,例如,您可以在输入字段上使用它。

    https://github.com/dnasir/angular-dateParser

    【讨论】:

      【解决方案3】:

      这应该可行:

      var setter = $parse('ngModel').assign;
      setter($scope,valueToSet);
      $scope.$apply() // This may be needed depending on where its done.
      

      参考:http://docs.angularjs.org/api/ng.$parse

      【讨论】:

      • 有一个错字:$prase -> $parse。即使那样,它也不能解决问题。
      【解决方案4】:

      在 html 上:

      <input class="form-control""
      type="date"
      string-to-date
      ng-model="val.VAL">
      

      在控制器上创建指令

      .directive('stringToDate', function() {
          return {
            require: 'ngModel',
            link: function(scope, element, attrs, ngModel) {
              ngModel.$parsers.push(function(value) {
                return new Date(value);
              });
              ngModel.$formatters.push(function(value) {
                var fechaactual = new Date(value);
                return fechaactual;
              });
            }
          };
        })
      

      请注意,该指令调用 stringToDate 并且您必须在 html 中将其称为 string-to-date。不要不知道为什么:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-09-12
        • 2013-05-25
        • 2019-09-05
        • 1970-01-01
        • 2017-09-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多