【问题标题】:AngularJs - Directive to modify input formattingAngularJs - 修改输入格式的指令
【发布时间】:2013-09-12 15:42:16
【问题描述】:

我想做以下事情:

我的控制器模型中有一个日期对象,我想让用户修改它。 应该给用户两个输入字段。 第一个输入字段应该修改日期,另一个是时间。 两个输入字段应该在相同的日期模型上工作。

<input ng-model="model.date" date-format="YYYY-MM-DD">
<input ng-model="model.date" date-format="HH:mm:SS">

我没有找到有关此绑定的文献。 通常,ng-model 指令负责输入字段的值。 现在我想用我自己的格式覆盖这个值。 此外,如果用户更改了输入,则应解析更改并将其放回日期对象中。

由于 vanilla js 中的日期操作有点奇怪,我使用 moment.js 来格式化和解析日期和字符串。

我目前的做法是这样的:

app.directive('dateFormat', function() {
    return {
        restrict: 'A',
        link: function(scope, el, at) {
            var format = at.dateFormat;
            scope.$watch(at.ngModel, function(date) {
                var result = moment(date).format(format);
                el.val(result);
            });
        }
    };
});

但是,一旦我想更改浏览器中的输入值,它就会中断。 我得到了一些 NaN:NaN...

我的问题是:

  • 如何建模?
  • 这种方法对角度哲学有效还是我在这里做了一些奇怪的事情?
  • 我可以同时使用 ng-model 和我的 date-format 指令吗?
  • 有更简单的方法吗?

【问题讨论】:

  • 那么,你有没有找到一个好的解决方案? :) 我处于类似的位置,我想将模型属性保留为 Date 对象,但仍允许用户在应用了日期掩码的编辑字段中对其进行编辑。

标签: javascript angularjs


【解决方案1】:

过滤器就是你要找的东西:

//In your controller
$scope.modelDate = $filter('date')(dateToFormat, "YYYY-MM-DD");

//In your view
<input ng-model="modelDate" type="text">

话虽如此,您尝试做的并不是太“关闭”,因为每当用户写入输入时,格式都会中断。您需要使用 ngModel,它有一种特殊的方式来处理 Directives(一种 API),并且可以作为链接过程中的第四个参数直接浏览。

所以对于您的代码,它会是这样的:

return {
  require: 'ngModel',
  link: function(scope, element, attrs, ngModelController) {
    ngModelController.$parsers.push(function(data) {
      //View -> Model
      return data;
    });
    ngModelController.$formatters.push(function(data) {
      //Model -> View
      return $filter('date')(data, "YYYY-MM-DD");
    });
  }
}

更多信息here

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,经过一些研究和测试,我想出了以下解决方案。它不会在每次击键期间对“模糊”执行所需的格式化和验证。查看评论标签以获取有关每个步骤的信息。您将需要 moment.js 来执行日期验证。

    myApp.directive('validDate', function ($filter, $window, $parse, $timeout) {
    return {
        require: '?ngModel',
        restrict: 'A',
        compile: function () {
            var moment = $window.moment;
            var getter, setter;
            return function (scope, element, attrs, ngModel) {
                //Declaring the getter and setter
                getter = $parse(attrs.ngModel);
                setter = getter.assign;
                //Set the initial value to the View and the Model
                ngModel.$formatters.unshift(function (modelValue) {
                    if (!modelValue) return "";
                    var retVal = $filter('date')(modelValue, "MM/dd/yyyy");
                    setter(scope, retVal);
                    console.log('Set initial View/Model value from: ' + modelValue + ' to ' + retVal);
                    return retVal;
                });
    
                // If the ngModel directive is used, then set the initial value and keep it in sync
                if (ngModel) {
                    element.on('blur', function (event) {
                        var date = moment($filter('date')(element.val(), "MM/dd/yyyy"));
                        // if the date entered is a valid date then save the value
                        if (date && moment(element.val(), "MM/DD/YYYY").isValid() && date <= moment() && date >= moment("01/01/1900")) {
                            element.css('background', 'white');
                            element[0].value = $filter('date')(date.toDate(), "MM/dd/yyyy");
                            console.log('change value to ' + element.val());
                            var newValue = element.val();
                            scope.$apply(function () {
                                setter(scope, newValue);
                            });
                        } else { //show an error and clear the value
                            console.log('INCORRECT VALUE ENTERED');
                            element.css('background', 'pink');
                            element[0].value = "";
                            scope.$apply(function () {
                                setter(scope, '');
                            });
                        }
                    });
                 }
             };
          }
      }; });
    

    该指令可以在视图中使用,如下所示:

    <input type="text" ng-model="member.BirthDate" required valid-date />
    

    【讨论】:

    • 抱歉,使用ngModel.$formatters 然后检查if (ngModel) 是没有意义的。
    猜你喜欢
    • 2013-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-23
    • 2014-04-20
    • 1970-01-01
    • 2021-03-23
    相关资源
    最近更新 更多