【问题标题】:Model is not a date object on input in AngularJS模型不是 AngularJS 中输入的日期对象
【发布时间】:2015-01-03 03:54:45
【问题描述】:

使用 AngularJS 我正在尝试使用输入 type=date 显示日期:

<input ng-model="campaign.date_start" type="date">

但是,这会产生以下错误:

Error: error:datefmt
Model is not a date object

日期实际上来自以下格式的 JSON API:

date_start": "2014-11-19"

我认为我可以通过使用过滤器来解决它,但这不起作用,我得到了同样的错误:

 <input ng-model="campaign.date_start | date" type="date">

我也尝试将字符串转换为日期,但我再次收到相同的错误:

 $scope.campaign.date_start = Date(campaign.date_start);

我还能尝试什么?

【问题讨论】:

  • 如果您尝试在控制台new Date("2014-11-19"); 中执行此操作,它可以正常工作,所以问题出在您的数据表示中。
  • Filter 不能在 ng-model 指令中使用,因为它必须是可赋值语句(即您必须能够为其赋值)。我没有尝试过下面提到的指令方法,但我确实找到了一个 $http 拦截器方法,它将日期格式的对象转换为 JavaScript 日期。这可以在aboutcode.net/2013/07/27/json-date-parsing-angularjs.html 找到

标签: javascript angularjs date


【解决方案1】:

你可以使用这个指令;

angular.module('app')
.directive("formatDate", function(){
  return {
   require: 'ngModel',
    link: function(scope, elem, attr, modelCtrl) {
      modelCtrl.$formatters.push(function(modelValue){
        return new Date(modelValue);
      })
    }
  }
})

在你的 html 中;

<input type="date" ng-model="date" format-date>

$formatters

Array.&lt;Function&gt;

每当模型值发生变化时,作为管道执行的函数数组。这些函数以相反的数组顺序调用,每个函数都将值传递给下一个。最后一个返回值用作实际的 DOM 值。用于格式化/转换值以在控件中显示。

【讨论】:

  • 这是我一直在寻找的解决方案,但是,当我尝试使用它时,我一直收到此错误Error: ngModel:datefmt Model is not a date object,尽管我的指令以比内置输入更高的优先级运行[日期] 指令。
  • @threed,我敢打赌,您的 HTML 中输入的日期不止一个。如果是这样,您将在每个没有 format-date 属性的日期输入上收到错误消息。这让我上当了一段时间。
  • 很好地解决了这个问题。但我有点恼火,这个问题首先存在。为什么框架不为我们处理这个?现在我们必须解析 serverkode(因为我们无法从 JSON 响应中获取 JavaScript Date 对象)或编写指令来使用日期输入。
  • 还想提一下,在读取from日期输入时也可以操作日期(例如,将数据保存到服务器时):使用 $parsers 方法相同上面的答案中使用了 $formatters。
  • 我添加了一个 if 以防您的模型包含可为空的日期 if (modelValue != null) return new Date(modelValue);
【解决方案2】:

您必须用Date 实例化campaign.date_start,而不是将其用作函数。

它应该看起来像这样 (small demo):

$scope.campaign.date_start = new Date(campaign.date_start);

【讨论】:

  • 与“新”一词一起使用,即新日期()谢谢
【解决方案3】:

cs1707 的指令非常棒,除非日期的范围值为nullundefined,那么它将使用1/1/1970 初始化一个日期。对于大多数人来说,这可能不是最佳选择

以下是 cs1707 指令的修改版本,它将保留 null/undefined 模型原样:

angular.module('app').directive("formatDate", function() {
    return {
        require: 'ngModel',
        link: function(scope, elem, attr, modelCtrl) {
            modelCtrl.$formatters.push(function(modelValue) {
                if (modelValue){
                    return new Date(modelValue);
                }
                else {
                    return null;
                }
            });
        }
    };
});

在你的 html 中;

<input type="date" ng-model="date" format-date>

另一种选择

如果您希望这适用于所有日期类型的输入,则无需将 format-date 属性添加到每个输入元素。您可以使用以下指令。 (注意这一点,因为它可能会以意想不到的方式与其他自定义指令交互。)

angular.module('app').directive("input", function() {
    return {
        require: 'ngModel',
        link: function(scope, elem, attr, modelCtrl) {
            if (attr['type'] === 'date'){
                modelCtrl.$formatters.push(function(modelValue) {
                    if (modelValue){
                        return new Date(modelValue);
                    }
                    else {
                        return null;
                    }
                });
            }

        }
    };
});

在你的 html 中;

<input type="date" ng-model="date">

【讨论】:

    【解决方案4】:

    这里的另一个指令解决方案:

    //inside directives.js
    .directive('dateField', function () {
        return {
            restrict: ' E',
            scope: {
                ngBind: '=ngModel',
                ngLabel: '@'
            },
            replace: true,
            require: 'ngModel',
            controller: function ($scope) {
                if ($scope.ngBind != null) {
                    var pattern = /Date\(([^)]+)\)/;
                    var results = pattern.exec($scope.ngBind);
                    var dt = new Date(parseFloat(results[1]));
                    $scope.ngBind = dt;
                };
            },
            templateUrl: 'templates/directives/dateField.html'
        }
    })
    ;
    

    像这样添加指令模板:

    <!-- app.directives templates/directives/dateField -->
    <script id="templates/directives/dateField.html" type="text/ng-template">    
        <label class="item item-input item-stacked-label ">
            <span class="input-label">{{ngLabel}}</span>
            <input type="date" placeholder="" ng-model="ngBind" />
        </label>
    </script>
    

    并使用它

    <date-field ng-label="This date..." ng-model="datajson.do.date"></date-field>
    

    祝你好运!

    【讨论】:

      【解决方案5】:

      使用指令通过ngModelCtrl.$formatters.length = 0; ngModelCtrl.$parsers.length = 0;重置默认角度格式化程序/解析器

      它适用于 input[type="date"]input[type="time"]。也适用于cordova应用程序

      HTML:

      <input date-input type="time" ng-model="created_time">
      

      角度指令:

      app.directive('dateInput', function () {
          return {
              require: 'ngModel',
              link: function (scope, element, attr, ngModelCtrl) {
                  //Angular 1.3 insert a formater that force to set model to date object, otherwise throw exception.
                  //Reset default angular formatters/parsers
                  ngModelCtrl.$formatters.length = 0;
                  ngModelCtrl.$parsers.length = 0;
              }
          };
      });
      

      【讨论】:

        【解决方案6】:

        另一种使用指令的简单方法:

        HTML:

        <input date-input type="time" ng-model="created_time">
        

        指令:

        app.directive('dateInput', function(){
            return {
                restrict : 'A',
                scope : {
                    ngModel : '='
                },
                link: function (scope) {
                    if (scope.ngModel) scope.ngModel = new Date(scope.ngModel);
                }
            }
        });
        

        【讨论】:

        • 请记住,虽然这足以满足您的初始摘要,但如果在另一个摘要周期中更改或刷新底层模型,这将不起作用。
        【解决方案7】:

        当我们将日期传递给某个函数或 API 时,您可以使用这段代码避免此错误,这实际上是日期格式错误

                    var options = {
                        weekday: "long", year: "numeric", month: "short",
                        day: "numeric", hour: "2-digit", minute: "2-digit"
                    };
                    $scope.campaign.date_start = $scope.campaign.date_start.toLocaleTimeString("en-us", options);
        

        其中 en-us 格式 = Friday‎, ‎Feb‎ ‎1‎, ‎2013‎ ‎06‎:‎00‎ ‎AM 希望这能帮助其他人解决问题,我遇到了这样的错误并解决了这个问题。

        【讨论】:

          猜你喜欢
          • 2016-02-06
          • 1970-01-01
          • 2015-09-14
          • 1970-01-01
          • 2018-04-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-05
          相关资源
          最近更新 更多