Подтвердить что ты не робот

Angular.js и входное значение даты в формате HTML5 - как заставить Firefox показать читаемое значение даты во вводе даты?

У меня есть ввод даты HTML5, и я бы хотел, чтобы его значение было установлено на значение свойства date в моей модели по умолчанию. Я не слишком суетлив к форматированию, поскольку Chrome, похоже, решил, что для меня в любом случае зависит от моего языка, но в идеале формат будет последовательно dd/MM/yyyy.

Fiddle

Вот как я настроил свой ввод:

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

Это отлично работает в Chrome, и по умолчанию я вижу следующее:

Chrome displaying the formatted value of the date

(Я все еще не совсем понимаю, почему значение должно было быть указано в yyyy-MM-dd, если Chrome по-прежнему форматирует его на основе моей локали, но это другой вопрос.)

Моя проблема заключается в том, что Firefox не показывает значение даты так, как я указал. Я думаю, что это связано с привязкой ввода к модели date, потому что я могу указать почти любую строку в атрибуте value, и по-прежнему буду видеть длинную строку даты на входе по умолчанию:

Firefox showing datestring

Если я удаляю ng-model="date" из входного тега, Firefox прекрасно отображает любое значение, которое я ему даю. Я не думал, что модель, связанная с вводом, фактически повлияла на ее значение по умолчанию?

Я понимаю, что ввод даты не поддерживается повсеместно, но, видя, что он должен возвращаться к простому текстовому вводу, я не понимаю, почему его значение не будет просто 2013-08-05, как указано angular фильтр даты.

Итак, как я могу заставить Firefox принять мое форматированное значение во вводе даты?


ПРИМЕЧАНИЕ После того как изменения были сделаны пользователем, я, конечно же, проведу валидацию и преобразую каждое входное значение даты в правильный date объект. Не уверен, что это имеет отношение к вопросу, но выставляя его там на всякий случай, потому что входные форматы, очевидно, должны быть согласованы, чтобы преобразование даты работало одинаково во всех браузерах. Проблематично, конечно, с Chrome, определяющим формат ввода для меня...

4b9b3361

Ответ 1

Проблема заключается в том, что value игнорируется, когда присутствует ng-model.

Firefox, который в настоящее время не поддерживает type="date", преобразует все значения в строку. Поскольку вы (по праву) хотите, чтобы 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

Фактическая структура предназначена только для демонстрационных целей. Вам лучше создать собственную директиву, особенно для того, чтобы:

Обратите внимание, что я использовал yyyy-MM-dd, потому что это формат, напрямую поддерживаемый объектом JavaScript 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,
  • проверьте правильность введенной пользователем даты.

Ответ 2

Почему значение должно было быть задано в yyyy-MM-dd?

В соответствии с input type = date spec HTML 5 значение должно быть в формате yyyy-MM-dd, так как оно принимает формат действительного full-date, который указан в RFC3339 как

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

Не имеет ничего общего с Angularjs, поскольку директивный ввод не поддерживает тип date.

Как заставить Firefox принимать мое форматированное значение во вводе даты?

FF не поддерживает тип ввода date, по крайней мере, до версии 24.0. Вы можете получить эту информацию от здесь. Итак, прямо сейчас, если вы используете ввод с типом date в FF, текстовое поле принимает любое значение, которое вы передаете.

Мое предложение - вы можете использовать Angular -ui Timepicker и не использовать поддержку HTML5 для ввода даты.

Ответ 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>

Ответ 4

В моем случае я решил так:

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

и дата ввода типа в порядке

Ответ 5

Я использовал 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>

Ответ 6

Проверьте эту полнофункциональную директиву для 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);
        })

      }
    };
  });

JADE/HTML:

div(date-input, ng-model="modelDate")

Ответ 7

При использовании Angular Material Design вы можете использовать компонент datepicker, и это будет работать в Firefox, IE и т.д.

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

Справедливое предупреждение, хотя - личный опыт заключается в том, что с этим возникают проблемы, и, похоже, он сейчас перерабатывается. См. Здесь:

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