Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allow Moment.js dates in bootstrap-ui datepicker

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?

like image 598
Slava Fomin II Avatar asked Dec 23 '14 19:12

Slava Fomin II


2 Answers

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;
  • minDate and maxDate $watches 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.

like image 50
Igor de Lorenzi Avatar answered Nov 14 '22 14:11

Igor de Lorenzi


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"

like image 45
startswithaj Avatar answered Nov 14 '22 16:11

startswithaj