I'm trying to use Bootstrap UI's DatePicker with Moment.js dates.
It is possible if I convert my model value from Moment.js date to standard Date
prior to assigning it to a scope:
$scope.myDate = moment('2014-11-07T21:20:15').toDate();
However, I would like it to be as transparent as possible, i.e. without the need for manual prior conversion.
I've tried to add wrapping formatters and parsers via directive extension, but it's not working as I'm expecting:
angular
.module('DatepickerWorkaround', [])
.directive('datepickerPopup', function () {
return {
restrict: 'EAC',
require: 'ngModel',
priority: -10,
link: function ($scope, element, attrs, ngModel) {
// Remove the default formatter from the input directive to prevent conflict.
// This is required for compatibility with AngularJS 1.3.x.
ngModel.$formatters.shift();
// Casting Moment.js date to standard date.
ngModel.$formatters.unshift(function(momentDate) {
if (moment.isMoment(momentDate)) {
return momentDate.toDate();
}
});
// Casting standard date back to Moment.js date.
ngModel.$parsers.push(function(date) {
if (date instanceof Date) {
return moment(date);
}
});
}
}
})
;
With this extension date is displayed correctly in the input field, but when popup opens the incorrect date is selected inside of it.
Also, I'm not quite sure what value should I use for directive priority
property and what methods should I call on $formatters
and $parsers
, i.e. push()
vs unshift()
.
Is there a way to make Bootstrap UI's DatePicker work with Moment.js dates transparently?
Decorating the original datepickerPopup
and datepicker
directives it's possible to achieve this conversion.
In this plunker I've changed the following methods:
ngModel.$render
on datepickerPopup;parseDate
on datepickerPopup;$watch
es on datepicker;this.render
on datepicker;this.refreshView
on datepicker;this.createDateObject
on datepicker;$scope.select
on datepicker;with moment.utc() and I'm pretty satisfied with the results. Let me know if it works for you.
I haven't tested this but you might be able to do this.
Create a customer filter that that returns the normal date...something like the below
angular.module('phonecatFilters', []).filter('momentToDate', function() {
return function(momentDate) {
if (moment.isMoment(momentDate)) {
return momentDate.toDate();
}else { return momentDate }
};
});
Then where you declare you directive
ng-model="yourmomentdate | momentToDate"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With