I am using bootstrap date-picker in my angular application. However when I select a date from that date-picker underlying ng-model that I have bind gets updated I want that ng-model in one date format 'MM/dd/yyyy'. but it every times makes date like this
"2009-02-03T18:30:00.000Z"
instead of
02/04/2009
I have created a plunkr for the same plunkr link
My Html and controller code is like below
<!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 controller
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';
};
Thanks in advance for review my question.
UPDATE
I am calling below method for posting my data and VAR is array of size 900 which contains date-picker variables.
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;
}
This question is related to
angularjs
datepicker
angular-ui
angular-ui-bootstrap
angular-ngmodel
Although similar answers have been posted I'd like to contribute what seemed to be the easiest and cleanest fix to me. Assuming you are using the AngularUI datepicker and your initial value for the ng-Model does not get formatted simply adding the following directive to your project will fix the issue:
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();
}
}
});
I found this solution in the Github AngularUI issues and therefore all credit goes to the people over there.
Finally I got work around to the above problem. angular-strap has exactly the same feature that I am expecting. Just by applying date-format="MM/dd/yyyy" date-type="string"
I got my expected behavior of updating ng-model in given format.
<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>
here is working plunk link
I can fix this by adding below code in my JSP file. Now both model and UI values are same.
<div ng-show="false">
{{dt = (dt | date:'dd-MMMM-yyyy') }}
</div>
I ran into the same problem and after a couple of hours of logging and investigating, I fixed it.
It turned out that for the first time the value is set in a date picker, $viewValue is a string so the dateFilter displays it as is. All I did is parse it into a Date object.
Search for that block in ui-bootstrap-tpls file
ngModel.$render = function() {
var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '';
element.val(date);
updateCalendar();
};
and replace it by:
ngModel.$render = function() {
ngModel.$viewValue = new Date(ngModel.$viewValue);
var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '';
element.val(date);
updateCalendar();
};
Hopefully this will help :)
The format
specified through datepicker-popup
is just the format for the displayed date. The underlying ngModel
is a Date object. Trying to display it will show it as it's default, standard-compliant rapresentation.
You can show it as you want by using the date
filter in the view, or, if you need it to be parsed in the controller, you can inject $filter
in your controller and call it as $filter('date')(date, format)
. See also the date filter docs.
You can make use of $parsers as shown below,this solved it for me.
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>
The datepicker (and datepicker-popup) directive requires that the ng-model be a Date object. This is documented here.
If you want ng-model to be a string in specific format, you should create a wrapper directive. Here is an example (Plunker):
(function () {_x000D_
'use strict';_x000D_
_x000D_
angular_x000D_
.module('myExample', ['ngAnimate', 'ngSanitize', 'ui.bootstrap'])_x000D_
.controller('MyController', MyController)_x000D_
.directive('myDatepicker', myDatepickerDirective);_x000D_
_x000D_
MyController.$inject = ['$scope'];_x000D_
_x000D_
function MyController ($scope) {_x000D_
$scope.dateFormat = 'dd MMMM yyyy';_x000D_
$scope.myDate = '30 Jun 2017';_x000D_
}_x000D_
_x000D_
myDatepickerDirective.$inject = ['uibDateParser', '$filter'];_x000D_
_x000D_
function myDatepickerDirective (uibDateParser, $filter) {_x000D_
return {_x000D_
restrict: 'E',_x000D_
scope: {_x000D_
name: '@',_x000D_
dateFormat: '@',_x000D_
ngModel: '='_x000D_
},_x000D_
required: 'ngModel',_x000D_
link: function (scope) {_x000D_
_x000D_
var isString = angular.isString(scope.ngModel) && scope.dateFormat;_x000D_
_x000D_
if (isString) {_x000D_
scope.internalModel = uibDateParser.parse(scope.ngModel, scope.dateFormat);_x000D_
} else {_x000D_
scope.internalModel = scope.ngModel;_x000D_
}_x000D_
_x000D_
scope.open = function (event) {_x000D_
event.preventDefault();_x000D_
event.stopPropagation();_x000D_
scope.isOpen = true;_x000D_
};_x000D_
_x000D_
scope.change = function () {_x000D_
if (isString) {_x000D_
scope.ngModel = $filter('date')(scope.internalModel, scope.dateFormat);_x000D_
} else {_x000D_
scope.ngModel = scope.internalModel;_x000D_
}_x000D_
};_x000D_
_x000D_
},_x000D_
template: [_x000D_
'<div class="input-group">',_x000D_
'<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()">',_x000D_
'<span class="input-group-btn">',_x000D_
'<button class="btn btn-default" ng-click="open($event)"> <i class="glyphicon glyphicon-calendar"></i> </button>',_x000D_
'</span>',_x000D_
'</div>'_x000D_
].join('')_x000D_
}_x000D_
}_x000D_
_x000D_
})();
_x000D_
<!DOCTYPE html>_x000D_
<html>_x000D_
_x000D_
<head>_x000D_
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>_x000D_
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script>_x000D_
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-sanitize.js"></script>_x000D_
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.js"></script>_x000D_
<script src="example.js"></script>_x000D_
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">_x000D_
</head>_x000D_
_x000D_
<body ng-app="myExample">_x000D_
<div ng-controller="MyController">_x000D_
<p>_x000D_
Date format: {{dateFormat}}_x000D_
</p>_x000D_
<p>_x000D_
Value: {{myDate}}_x000D_
</p>_x000D_
<p>_x000D_
<my-datepicker ng-model="myDate" date-format="{{dateFormat}}"></my-datepicker>_x000D_
</p>_x000D_
</div>_x000D_
</body>_x000D_
_x000D_
</html>
_x000D_
With so many answers already written, Here's my take.
With Angular 1.5.6 & ui-bootstrap 1.3.3 , just add this on the model & you are done.
ng-model-options="{timezone: 'UTC'}"
Note: Use this only if you are concerned about the date being 1 day behind & not bothered with extra time of T00:00:00.000Z
Updated Plunkr Here :
All proposed solutions didn't work for me but the closest one was from @Rishii.
I'm using AngularJS 1.4.4 and 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;
}
};
}
};
}])
Defining a new directive to work around a bug is not really ideal.
Because the datepicker displays later dates correctly, one simple workaround could be just setting the model variable to null first, and then to the current date after a while:
$scope.dt = null;
$timeout( function(){
$scope.dt = new Date();
},100);
Steps to change the default date format of ng-model
For different date formats check the jqueryui datepicker date format values here for example I have used dd/mm/yy
Create angularjs directive
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');
});
}
}
});
Write dateFilter function
function dateFilter(val,format) {
return $.datepicker.formatDate(format,val);
}
In html page write the ng-modal attribute
<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 />
After checking the above answers, I came up with this and it worked perfectly without having to add an extra attribute to your markup
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');
});
}
}
});
You may use formatters after picking value inside your datepicker directive. For example
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;
});
}
};
});
LINK.
Source: Stackoverflow.com