Угловой bootstrap datepicker формат даты не форматирует значение ng-model
я использую bootstrap date-picker в своем угловом приложении. Однако, когда я выбираю дату из этого выбора даты, лежащего в основе ng-модели, которую я связываю, обновляется, я хочу, чтобы эта ng-модель была в одном формате даты "MM/dd/yyyy". но это каждый раз делает дату, как это
"2009-02-03T18:30:00.000Z"
вместо
02/04/2009
Я создал plunkr для той же plunkr link
мой Html и контроллер код, как ниже
<!doctype html>
<html ng-app="plunker">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="DatepickerDemoCtrl">
<pre>Selected date is: <em>{{dt | date:'MM/dd/yyyy' }}</em></pre>
<p>above filter will just update above UI but I want to update actual ng-modle</p>
<h4>Popup</h4>
<div class="row">
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control"
datepicker-popup="{{format}}"
ng-model="dt"
is-open="opened" min-date="minDate"
max-date="'2015-06-22'"
datepicker-options="dateOptions"
date-disabled="disabled(date, mode)"
ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open($event)">
<i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
</div>
<!--<div class="row">
<div class="col-md-6">
<label>Format:</label> <select class="form-control" ng-model="format" ng-options="f for f in formats"><option></option></select>
</div>
</div>-->
<hr />
{{dt}}
</div>
</body>
</html>
угловой контроллер
angular.module('plunker', ['ui.bootstrap']);
var DatepickerDemoCtrl = function ($scope) {
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};
$scope.dateOptions = {
formatYear: 'yy',
startingDay: 1
};
$scope.format = 'dd-MMMM-yyyy';
};
заранее спасибо за обзор моего вопроса.
обновление
Я вызываю ниже метод для размещения моих данных и VAR-это массив размером 900, который содержит переменные выбора даты.
public SaveCurrentData(formToSave: tsmodels.ResponseTransferCalculationModelTS) {
var query = this.EntityQuery.from('SaveFormData').withParameters({
$method: 'POST',
$encoding: 'JSON',
$data: {
VAR: formToSave.VAR,
X: formToSave.X,
CurrentForm: formToSave.currentForm,
}
});
var deferred = this.q.defer();
this.manager.executeQuery(query).then((response) => {
deferred.resolve(response);
}, (error) => {
deferred.reject(error);
});
return deferred.promise;
}
13 ответов:
хотя подобные ответы были опубликованы, я хотел бы внести свой вклад в то, что казалось мне самым простым и чистым решением. предполагая, что вы используете AngularUI datepicker и ваше начальное значение для ng-модели не форматируется, просто добавив следующую директиву в ваш проект, устранит проблему:
angular.module('yourAppName') .directive('datepickerPopup', function (){ return { restrict: 'EAC', require: 'ngModel', link: function(scope, element, attr, controller) { //remove the default formatter from the input directive to prevent conflict controller.$formatters.shift(); } } });
Я нашел это решение в вопросы GitHub AngularUI и поэтому весь кредит идет к людям там.
Вы можете использовать $parsers,как показано ниже, это решило его для меня.
window.module.directive('myDate', function(dateFilter) { return { restrict: 'EAC', require: '?ngModel', link: function(scope, element, attrs, ngModel) { ngModel.$parsers.push(function(viewValue) { return dateFilter(viewValue,'yyyy-MM-dd'); }); } }; });
HTML:
<p class="input-group datepicker" > <input type="text" class="form-control" name="name" datepicker-popup="yyyy-MM-dd" date-type="string" show-weeks="false" ng-model="data[$parent.editable.name]" is-open="$parent.opened" min-date="minDate" close-text="Close" ng-required="{{editable.mandatory}}" show-button-bar="false" close-on-date-selection="false" my-date /> <span class="input-group-btn"> <button type="button" class="btn btn-default" ng-click="openDatePicker($event)"> <i class="glyphicon glyphicon-calendar"></i> </button> </span> </p>
я столкнулся с той же проблемой и после нескольких часов регистрации и расследования, я исправил это.
оказалось, что впервые значение задается в средстве выбора даты, $viewValue является строкой, поэтому фильтр даты отображает его как есть. Все, что я сделал, это разобрать его на объект даты.
поиск этого блока в файле ui-bootstrap-tpls
ngModel.$render = function() { var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : ''; element.val(date); updateCalendar(); };
и заменить его на:
ngModel.$render = function() { ngModel.$viewValue = new Date(ngModel.$viewValue); var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : ''; element.val(date); updateCalendar(); };
надеюсь, это поможет :)
The
format
указаноdatepicker-popup
это просто формат отображаемой даты. Лежащий в основеngModel
представляет собой объект Date. Попытка отобразить его покажет его как это по умолчанию, стандартно-совместимый rapresentation.вы можете показать его, как вы хотите с помощью
date
фильтр в представлении, или, если вам нужно его разобрать в контроллере, вы можете ввести$filter
в вашем контроллере и назовите его как$filter('date')(date, format)
. Смотрите также раздел дата фильтр документы.
вы можете использовать средства форматирования после выбора значения в вашем директиве управления datepicker. Например
angular.module('foo').directive('bar', function() { return { require: '?ngModel', link: function(scope, elem, attrs, ctrl) { if (!ctrl) return; ctrl.$formatters.push(function(value) { if (value) { // format and return date here } return undefined; }); } }; });
С таким количеством ответов уже написано, вот мое мнение.
С угловой 1.5.6 & ui-bootstrap 1.3.3, просто добавьте это на модели и вы сделали.
ng-model-options="{timezone: 'UTC'}"
Примечание: используйте это только в том случае, если вы обеспокоены тем, что дата отстает на 1 день и не беспокоится о дополнительном времени T00:00:00.000 Z
Обновлено Plunkr Здесь :
все предложенные решения не работали для меня, но самый близкий был от @Rishii.
Я использую AngularJS 1.4.4 и UI Bootstrap 0.13.3.
.directive('jsr310Compatible', ['dateFilter', 'dateParser', function(dateFilter, dateParser) { return { restrict: 'EAC', require: 'ngModel', priority: 1, link: function(scope, element, attrs, ngModel) { var dateFormat = 'yyyy-MM-dd'; ngModel.$parsers.push(function(viewValue) { return dateFilter(viewValue, dateFormat); }); ngModel.$validators.date = function (modelValue, viewValue) { var value = modelValue || viewValue; if (!attrs.ngRequired && !value) { return true; } if (angular.isNumber(value)) { value = new Date(value); } if (!value) { return true; } else if (angular.isDate(value) && !isNaN(value)) { return true; } else if (angular.isString(value)) { var date = dateParser.parse(value, dateFormat); return !isNaN(date); } else { return false; } }; } }; }])
Я могу исправить это, добавив следующий код в мой файл JSP. Теперь оба значения модели и пользовательского интерфейса одинаковы.
<div ng-show="false"> {{dt = (dt | date:'dd-MMMM-yyyy') }} </div>
шаги по изменению формата даты по умолчанию ng-model
для разных форматов даты проверьте значения формата даты jQueryUI datepicker здесь, например, я использовал dd/mm / yy
создать директиву angularjs
angular.module('app', ['ui.bootstrap']).directive('dt', function () { return { restrict: 'EAC', require: 'ngModel', link: function (scope, element, attr, ngModel) { ngModel.$parsers.push(function (viewValue) { return dateFilter(viewValue, 'dd/mm/yy'); }); } } });
написать функцию фильтра даты
function dateFilter(val,format) { return $.datepicker.formatDate(format,val); }
в html-странице напишите атрибут ng-modal
<input type="text" class="form-control" date-type="string" uib-datepicker-popup="{{format}}" ng-model="src.pTO_DATE" is-open="popup2.opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" show-button-bar="false" show-weeks="false" dt />
наконец-то я нашел отличное решение этой проблемы. угловой ремень имеет точно такую же функцию, которую я ожидаю. Только путем применения
date-format="MM/dd/yyyy" date-type="string"
Я получил мое ожидаемое поведение обновления ng-модели в данном формате.<div class="bs-example" style="padding-bottom: 24px;" append-source> <form name="datepickerForm" class="form-inline" role="form"> <!-- Basic example --> <div class="form-group" ng-class="{'has-error': datepickerForm.date.$invalid}"> <label class="control-label"><i class="fa fa-calendar"></i> Date <small>(as date)</small></label> <input type="text" autoclose="true" class="form-control" ng-model="selectedDate" name="date" date-format="MM/dd/yyyy" date-type="string" bs-datepicker> </div> <hr> {{selectedDate}} </form> </div>
здесь работает plunk ссылке
определение новой директивы для работы с ошибкой на самом деле не идеально.
поскольку datepicker отображает более поздние даты правильно, одним из простых обходных путей может быть просто установка переменной модели сначала на null, а затем на текущую дату через некоторое время:
$scope.dt = null; $timeout( function(){ $scope.dt = new Date(); },100);
директива datepicker (и datepicker-popup) требует, чтобы ng-модель была объектом Date. Это задокументировано здесь.
Если вы хотите, чтобы ng-модель была строкой в определенном формате, вы должны создать директиву-оболочку. Вот пример (Plunker):
(function () { 'use strict'; angular .module('myExample', ['ngAnimate', 'ngSanitize', 'ui.bootstrap']) .controller('MyController', MyController) .directive('myDatepicker', myDatepickerDirective); MyController.$inject = ['$scope']; function MyController ($scope) { $scope.dateFormat = 'dd MMMM yyyy'; $scope.myDate = '30 Jun 2017'; } myDatepickerDirective.$inject = ['uibDateParser', '$filter']; function myDatepickerDirective (uibDateParser, $filter) { return { restrict: 'E', scope: { name: '@', dateFormat: '@', ngModel: '=' }, required: 'ngModel', link: function (scope) { var isString = angular.isString(scope.ngModel) && scope.dateFormat; if (isString) { scope.internalModel = uibDateParser.parse(scope.ngModel, scope.dateFormat); } else { scope.internalModel = scope.ngModel; } scope.open = function (event) { event.preventDefault(); event.stopPropagation(); scope.isOpen = true; }; scope.change = function () { if (isString) { scope.ngModel = $filter('date')(scope.internalModel, scope.dateFormat); } else { scope.ngModel = scope.internalModel; } }; }, template: [ '<div class="input-group">', '<input type="text" readonly="true" style="background:#fff" name="{{name}}" class="form-control" uib-datepicker-popup="{{dateFormat}}" ng-model="internalModel" is-open="isOpen" ng-click="open($event)" ng-change="change()">', '<span class="input-group-btn">', '<button class="btn btn-default" ng-click="open($event)"> <i class="glyphicon glyphicon-calendar"></i> </button>', '</span>', '</div>' ].join('') } } })();
<!DOCTYPE html> <html> <head> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-sanitize.js"></script> <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.js"></script> <script src="example.js"></script> <link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> </head> <body ng-app="myExample"> <div ng-controller="MyController"> <p> Date format: {{dateFormat}} </p> <p> Value: {{myDate}} </p> <p> <my-datepicker ng-model="myDate" date-format="{{dateFormat}}"></my-datepicker> </p> </div> </body> </html>
после проверки вышеуказанных ответов я придумал это, и он отлично работал без необходимости добавлять дополнительный атрибут к вашей разметке
angular.module('app').directive('datepickerPopup', function(dateFilter) { return { restrict: 'EAC', require: 'ngModel', link: function(scope, element, attr, ngModel) { ngModel.$parsers.push(function(viewValue) { return dateFilter(viewValue, 'yyyy-MM-dd'); }); } } });