Allow Moment.js dates in bootstrap-ui datepicker

2019-03-25 02:39发布

问题:

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?

回答1:

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.



回答2:

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"