64

我有一个 HTML5 日期输入,我希望它的值默认设置为我模型中日期属性的值。我对格式化并不太挑剔,因为 Chrome 似乎会根据我的语言环境为我决定,但理想情况下,格式应该是一致的dd/MM/yyyy

小提琴

这就是我设置输入的方式:

<input type="date" 
       ng-model="date" 
       value="{{ date | date: 'yyyy-MM-dd' }}" />

这在 Chrome 上运行良好,默认情况下我会看到以下内容:

Chrome 显示日期的格式化值

(我仍然不太明白为什么必须在 中给出值yyyy-MM-dd,如果 Chrome 仍然根据我的语言环境对其进行格式化,但这是一个不同的问题。)

我的问题是 Firefox 没有按照我指定的方式显示日期值。我认为这与将输入绑定到date模型有关,因为我可以在属性中指定几乎任何字符串value,并且默认情况下我仍然会在输入中看到长日期字符串:

Firefox 显示日期字符串

如果我ng-model="date"从输入标签中删除,Firefox 会很好地显示我给它的任何值。我不认为输入绑定的模型实际上对其默认值有任何影响?

我知道日期输入不受普遍支持,但鉴于它应该依赖于简单的文本输入,我不明白为什么它的值不会2013-08-05像 Angular 的日期过滤器所指定的那样简单。

那么,如何让 Firefox 在日期输入中接受我的格式化值?


注意在用户完成编辑后,我当然会执行验证并将每个日期输入值转换为适当的Date对象。不确定这是否与问题相关,但将其放在那里以防万一,因为输入格式显然需要保持一致,以使日期转换在所有浏览器中都能正常工作。当然,Chrome 为我决定输入格式是有问题的……

4

7 回答 7

73

问题是当存在value时被忽略ng-model

目前不支持type="date"的 Firefox 会将所有值转换为字符串。由于您(正确地)想要date成为一个真实的Date对象而不是一个字符串,我认为最好的选择是创建另一个变量,例如dateString,然后链接这两个变量:

<input type="date" ng-model="dateString" />
function MainCtrl($scope, dateFilter) {
    $scope.date = new Date();

    $scope.$watch('date', function (date)
    {
        $scope.dateString = dateFilter(date, 'yyyy-MM-dd');
    });

    $scope.$watch('dateString', function (dateString)
    {
        $scope.date = new Date(dateString);
    });
}

Fiddle

实际结构仅用于演示目的。您最好创建自己的指令,尤其是为了:

请注意我使用了 ,因为它是 JavaScript对象yyyy-MM-dd直接支持的格式。Date如果您想使用另一个,您必须自己进行转换


编辑

这是一种制作干净指令的方法:

myModule.directive(
    'dateInput',
    function(dateFilter) {
        return {
            require: 'ngModel',
            template: '<input type="date"></input>',
            replace: true,
            link: function(scope, elm, attrs, ngModelCtrl) {
                ngModelCtrl.$formatters.unshift(function (modelValue) {
                    return dateFilter(modelValue, 'yyyy-MM-dd');
                });

                ngModelCtrl.$parsers.unshift(function(viewValue) {
                    return new Date(viewValue);
                });
            },
        };
});

Fiddle

这是一个基本指令,还有很大的改进空间,例如:

  • 允许使用自定义格式而不是yyyy-MM-dd,
  • 检查用户输入的日期是否正确。
于 2013-08-05T15:58:57.370 回答
12

为什么必须在 yyyy-MM-dd 中给出值?

根据 HTML 5 的input type = date 规范,该值必须采用格式yyyy-MM-dd,因为它采用RFC3339full-date中指定的有效格式为

full-date = date-fullyear "-" date-month "-" date-mday

date由于指令输入不支持类型,因此与 Angularjs 无关。

如何让 Firefox 在日期输入中接受我的格式化值?

dateFF至少在 24.0 版本之前不支持输入类型。您可以从此处获取此信息。因此,现在,如果您使用类型为dateFF 的输入,则文本框将采用您传入的任何值。

我的建议是你可以使用Angular-ui 的 Timepicker,不要使用 HTML5 支持日期输入。

于 2013-08-05T15:56:52.427 回答
3

你可以使用它,它工作正常:

<input type="date" class="form1"  
  value="{{date | date:MM/dd/yyyy}}"
  ng-model="date" 
  name="id" 
  validatedateformat 
  data-date-format="mm/dd/yyyy"
  maxlength="10" 
  id="id" 
  calendar 
  maxdate="todays"
  ng-click="openCalendar('id')">
    <span class="input-group-addon">
      <span class="glyphicon glyphicon-calendar" ng-click="openCalendar('id')"></span>
    </span>
</input>
于 2014-06-07T17:19:59.117 回答
2

就我而言,我已经解决了这种方式:

$scope.MyObject = // get from database or other sources;
$scope.MyObject.Date = new Date($scope.MyObject.Date);

并且输入类型日期是可以的

于 2016-06-05T03:05:12.960 回答
0

我用过 ng-change:

Date.prototype.addDays = function(days) {
  var dat = new Date(this.valueOf());
  dat.setDate(dat.getDate() + days);
  return dat;
}

var app = angular.module('myApp', []);

app.controller('DateController', ['$rootScope', '$scope',
  function($rootScope, $scope) {
    function init() {
      $scope.startDate = new Date();
      $scope.endDate = $scope.startDate.addDays(14);
    }


    function load() {
      alert($scope.startDate);
      alert($scope.endDate);
    }

    init();
    // public methods
    $scope.load = load;
    $scope.setStart = function(date) {
      $scope.startDate = date;
    };
    $scope.setEnd = function(date) {
      $scope.endDate = date;
    };

  }
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-controller="DateController">
  <label class="item-input"> <span class="input-label">Start</span>
    <input type="date" data-ng-model="startDate" ng-change="setStart(startDate)" required validatedateformat calendar>
  </label>
  <label class="item-input"> <span class="input-label">End</span>
    <input type="date" data-ng-model="endDate" ng-change="setEnd(endDate)" required validatedateformat calendar>
  </label>
  <button button="button" ng-disabled="planningForm.$invalid" ng-click="load()" class="button button-positive">
    Run
  </button>
</div <label class="item-input"> <span class="input-label">Start</span>
<input type="date" data-ng-model="startDate" ng-change="setStart(startDate)" required validatedateformat calendar>
</label>
<label class="item-input"> <span class="input-label">End</span>
  <input type="date" data-ng-model="endDate" ng-change="setEnd(endDate)" required validatedateformat calendar>
</label>

于 2015-02-04T11:46:20.060 回答
0

检查 MEAN.JS(Angular.js、bootstrap、Express.js 和 MongoDb)的这个功能齐全的指令

根据@Blackhole 的回复,我们刚刚完成了它以与 mongodb 和 express 一起使用。

它将允许您从 mongoose 连接器保存和加载日期

希望能帮助到你!!

angular.module('myApp')
.directive(
  'dateInput',
  function(dateFilter) {
    return {
      require: 'ngModel',
      template: '<input type="date" class="form-control"></input>',
      replace: true,
      link: function(scope, elm, attrs, ngModelCtrl) {
        ngModelCtrl.$formatters.unshift(function (modelValue) {
          return dateFilter(modelValue, 'yyyy-MM-dd');
        });

        ngModelCtrl.$parsers.push(function(modelValue){
           return angular.toJson(modelValue,true)
          .substring(1,angular.toJson(modelValue).length-1);
        })

      }
    };
  });

玉/HTML:

div(date-input, ng-model="modelDate")
于 2015-04-16T20:30:06.720 回答
0

如果使用 Angular Material Design,您可以在那里使用 datepicker 组件,这将适用于 Firefox、IE 等。

https://material.angularjs.org/latest/demo/datepicker

但公平警告 - 个人经验是这存在问题,目前似乎正在重新工作。看这里:

https://github.com/angular/material/issues/4856

于 2016-02-09T01:20:19.663 回答