Разрешить даты Moment.js в bootstrap-ui datepicker

Я пытаюсь использовать пользовательский интерфейс Bootstrap DatePicker с Moment.js.

Возможно, если я преобразую свое значение модели из даты Moment.js в стандартное Date до назначения его в область видимости:

$scope.myDate = moment('2014-11-07T21:20:15').toDate();

Однако я хотел бы, чтобы он был как можно более прозрачным, т.е. без необходимости предварительного преобразования вручную.

Я попытался добавить форматы и парсеры для переноса через расширение директивы, но он не работает так, как я ожидаю:

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);
                    }
                });
            }
        }
    })
;

С этой датой добавочного номера отображается правильно в поле ввода, но когда всплывающее окно открывается, внутри него выбирается некорректная дата.

Кроме того, я не совсем уверен, какое значение следует использовать для свойства директивы priority и какие методы следует использовать для $formatters и $parsers, т.е. push() vs unshift().

Есть ли способ сделать Bootstrap UI DatePicker работать с датами Moment.js прозрачно?

Ответ 1

Украшая оригинальные директивы datepickerPopup и datepicker, можно добиться этого преобразования.

В этом plunker я изменил следующие методы:

  • ngModel.$render в datepickerPopup;
  • parseDate в datepickerPopup;
  • minDate и maxDate $watch es на datepicker;
  • this.render в datepicker;
  • this.refreshView в datepicker;
  • this.createDateObject в datepicker;
  • $scope.select в datepicker;

с moment.utc(), и я очень доволен результатами. Дайте мне знать, если это сработает для вас.

Ответ 2

Я не тестировал это, но вы могли бы это сделать.

Создайте фильтр клиента, который возвращает нормальную дату... что-то вроде ниже

angular.module('phonecatFilters', []).filter('momentToDate', function() {
    return function(momentDate) {
        if (moment.isMoment(momentDate)) {
            return momentDate.toDate();
        }else { return momentDate }
    };
});

Затем, когда вы объявляете директиву ng-model="yourmomentdate | momentToDate"