AngularJs - 修改输入格式的指令

时间:2013-09-12 15:42:16

标签: javascript angularjs

我想做以下事情:

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

<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和我的日期格式指令吗?
  • 有更简单的方法吗?

2 个答案:

答案 0 :(得分:16)

您正在寻找过滤器:

//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

答案 1 :(得分:3)

我遇到了同样的问题,经过一些研究和测试后,我提出了以下解决方案。它可以在模糊&#39;上执行所需的格式和验证。不是在每次击键时。查看每个步骤的信息的注释标签。您将需要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, '');
                        });
                    }
                });
             }
         };
      }
  }; });

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

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