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, определяющим формат ввода для меня...
Ответы
Ответ 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