Как отформатировать дату с помощью ng-модели?
У меня есть вход, определенный как
<input class="datepicker" type="text" ng-model="clientForm.birthDate" />
который настроен для отображения в другом месте на странице:
<tr>
<th>Birth Date</th>
<td>{{client.birthDate|date:'mediumDate'}}</td>
</tr>
Когда страница загружается, дата рождения красиво отформатирована как что-то вроде Dec 22, 2009
. Однако, когда я просматриваю свой <input>
, он отображается как Tue Dec 22 2009 00:00:00 GMT-0800 (Pacific Standard Time)
, который, как я полагаю, является тем, что JS отображает объекты Date
как строки.
Во-первых, как сообщить Angular, чтобы показать дату в <input>
как что-то вроде 12/22/2009
? Я не могу применить |filters
к атрибуту ng-model
.
Во-вторых, как только я редактирую дату, даже сохраняя ее в оригинальном формате, мой другой текст (внутри <td>
), похоже, больше не применяет фильтр |date
; он неожиданно меняет форматы, соответствующие формату входного текстового поля. Как заставить его применять фильтр |date
каждый раз, когда изменяется модель?
Похожие вопросы:
Ответы
Ответ 1
Использовать пользовательскую проверку форм http://docs.angularjs.org/guide/forms Демо: http://plnkr.co/edit/NzeauIDVHlgeb6qF75hX?p=preview
Директива с использованием форматировщиков и парсеров и MomentJS)
angModule.directive('moDateInput', function ($window) {
return {
require:'^ngModel',
restrict:'A',
link:function (scope, elm, attrs, ctrl) {
var moment = $window.moment;
var dateFormat = attrs.moDateInput;
attrs.$observe('moDateInput', function (newValue) {
if (dateFormat == newValue || !ctrl.$modelValue) return;
dateFormat = newValue;
ctrl.$modelValue = new Date(ctrl.$setViewValue);
});
ctrl.$formatters.unshift(function (modelValue) {
if (!dateFormat || !modelValue) return "";
var retVal = moment(modelValue).format(dateFormat);
return retVal;
});
ctrl.$parsers.unshift(function (viewValue) {
var date = moment(viewValue, dateFormat);
return (date && date.isValid() && date.year() > 1950 ) ? date.toDate() : "";
});
}
};
});
Ответ 2
Вот очень удобная директива angular-datetime.
Вы можете использовать его следующим образом:
<input type="text" datetime="yyyy-MM-dd HH:mm:ss" ng-model="myDate">
Он также добавляет маску к вашему входу и выполняет проверку.
Ответ 3
Я создал простую директиву, позволяющую стандартным элементам формы input[type="date"]
корректно работать с AngularJS ~ 1.2.16.
Посмотрите здесь:
https://github.com/betsol/angular-input-date
И вот демо:
http://jsfiddle.net/F2LcY/1/
Ответ 4
Так как вы использовали datepicker как класс, я предполагаю, что вы используете JQuery datepicker или что-то подобное.
Существует способ делать то, что вы намереваетесь, без использования moment.js вообще, используя только директивы datepicker и angularjs.
Я привел пример здесь в Fiddle
Выдержки из скрипки здесь:
-
Datepicker имеет другой формат, а формат angularjs отличается, необходимо найти соответствующее совпадение, чтобы дата была предварительно выбрана в элементе управления и также заполнена в поле ввода, когда привязана ng-модель. Следующий формат эквивалентен формату 'mediumDate'
формата AngularJS.
$(element).find(".datepicker")
.datepicker({
dateFormat: 'M d, yy'
});
-
Директива ввода даты должна иметь промежуточную строковую переменную для представления читаемой формы даты.
-
Обновление через разные разделы страницы должно происходить через события, такие как $broadcast
и $on
.
-
Использование фильтра для представления даты в удобочитаемой форме человека возможно и в ng-модели, но с временной переменной модели.
$scope.dateValString = $filter('date')($scope.dateVal, 'mediumDate');
Ответ 5
Я использую jquery datepicker для выбора даты. Моя дата указания директивы и преобразование ее в формат даты json (в миллисекундах) хранятся в данных ng-model
во время отображения даты date.and reverse, если ng-model имеет json date (в миллисекунде) мой дисплей форматирования в моем формате как jquery datepicker.
Код HTML:
<input type="text" jqdatepicker ng-model="course.launchDate" required readonly />
Angular Директива:
myModule.directive('jqdatepicker', function ($filter) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModelCtrl) {
element.datepicker({
dateFormat: 'dd/mm/yy',
onSelect: function (date) {
var ar=date.split("/");
date=new Date(ar[2]+"-"+ar[1]+"-"+ar[0]);
ngModelCtrl.$setViewValue(date.getTime());
scope.$apply();
}
});
ngModelCtrl.$formatters.unshift(function(v) {
return $filter('date')(v,'dd/MM/yyyy');
});
}
};
});
Ответ 6
Я использую следующую директиву, которая делает меня и большинство пользователей очень счастливыми! Он использует момент для синтаксического анализа и форматирования. Это немного похоже на ту, что упоминается ранее SunnyShah.
angular.module('app.directives')
.directive('appDatetime', function ($window) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
var moment = $window.moment;
ngModel.$formatters.push(formatter);
ngModel.$parsers.push(parser);
element.on('change', function (e) {
var element = e.target;
element.value = formatter(ngModel.$modelValue);
});
function parser(value) {
var m = moment(value);
var valid = m.isValid();
ngModel.$setValidity('datetime', valid);
if (valid) return m.valueOf();
else return value;
}
function formatter(value) {
var m = moment(value);
var valid = m.isValid();
if (valid) return m.format("LLLL");
else return value;
}
} //link
};
}); //appDatetime
В моей форме я использую его следующим образом:
<label>begin: <input type="text" ng-model="doc.begin" app-datetime required /></label>
<label>end: <input type="text" ng-model="doc.end" app-datetime required /></label>
Это привяжет метку времени (миллисекунды с 1970 года) до doc.begin
и doc.end
.
Ответ 7
Я предпочитаю, чтобы сервер возвращал дату без изменений, и javascript делает просмотр массива. Мой API возвращает "MM/DD/YYYY hh: mm: ss" из SQL Server.
Ресурс
angular.module('myApp').factory('myResource',
function($resource) {
return $resource('api/myRestEndpoint/', null,
{
'GET': { method: 'GET' },
'QUERY': { method: 'GET', isArray: true },
'POST': { method: 'POST' },
'PUT': { method: 'PUT' },
'DELETE': { method: 'DELETE' }
});
}
);
контроллер
var getHttpJson = function () {
return myResource.GET().$promise.then(
function (response) {
if (response.myDateExample) {
response.myDateExample = $filter('date')(new Date(response.myDateExample), 'M/d/yyyy');
};
$scope.myModel= response;
},
function (response) {
console.log(response.data);
}
);
};
Директива по проверке myDate
angular.module('myApp').directive('myDate',
function($window) {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
var moment = $window.moment;
var acceptableFormats = ['M/D/YYYY', 'M-D-YYYY'];
function isDate(value) {
var m = moment(value, acceptableFormats, true);
var isValid = m.isValid();
//console.log(value);
//console.log(isValid);
return isValid;
};
ngModel.$parsers.push(function(value) {
if (!value || value.length === 0) {
return value;
};
if (isDate(value)) {
ngModel.$setValidity('myDate', true);
} else {
ngModel.$setValidity('myDate', false);
}
return value;
});
}
}
}
);
HTML
<div class="form-group">
<label for="myDateExample">My Date Example</label>
<input id="myDateExample"
name="myDateExample"
class="form-control"
required=""
my-date
maxlength="50"
ng-model="myModel.myDateExample"
type="text" />
<div ng-messages="myForm.myDateExample.$error" ng-if="myForm.$submitted || myForm.myDateExample.$touched" class="errors">
<div ng-messages-include="template/validation/messages.html"></div>
</div>
</div>
шаблон/проверки/messages.html
<div ng-message="required">Required Field</div>
<div ng-message="number">Must be a number</div>
<div ng-message="email">Must be a valid email address</div>
<div ng-message="minlength">The data entered is too short</div>
<div ng-message="maxlength">The data entered is too long</div>
<div ng-message="myDate">Must be a valid date</div>
Ответ 8
Angularjs ui bootstrap
вы можете использовать angularjs ui bootstrap, он также обеспечивает проверку даты
<input type="text" class="form-control"
datepicker-popup="{{format}}" ng-model="dt" is-open="opened"
min-date="minDate" max-date="'2015-06-22'" datepickeroptions="dateOptions"
date-disabled="disabled(date, mode)" ng-required="true">
в контроллере может указывать любой формат, который вы хотите отобразить в качестве даты-фильтра.
$ scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];