Подтвердить что ты не робот

Bootprap datepicker с привязкой к knockout.js

Этот вопрос похож на привязку к knockoutjs с jquery-ui datepicker, но вместо jQueryUI datepicker я хотел бы использовать один из Bootprap datepickers.

API для Bootstrap datepicker отличается от jquery-ui, и у меня возникают некоторые проблемы, обертывающие мою голову вокруг работы с knockout.js. Я создал jsFiddle, чтобы попробовать его.

Кажется, что Bootprap datepicker может быть намного проще использовать, потому что он не сохраняет дату. Тем не менее, я хотел бы знать, как jsFiddle является подходящим способом использования виджета Bootprap datepicker с knockout.js i.e.

ko.bindingHandlers.datepicker = {
    init: function(element, valueAccessor, allBindingsAccessor) {
      //initialize datepicker with some optional options
      var options = allBindingsAccessor().datepickerOptions || {};
      $(element).datepicker(options);

      ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $(element).datepicker("destroy");
        });
    },
    update: function(element, valueAccessor) {
    }
};
4b9b3361

Ответ 1

Вот пример того, как вы могли бы это сделать с помощью datepicker, который вы используете:

ko.bindingHandlers.datepicker = {
    init: function(element, valueAccessor, allBindingsAccessor) {
      //initialize datepicker with some optional options
      var options = allBindingsAccessor().datepickerOptions || {};
      $(element).datepicker(options);

      //when a user changes the date, update the view model
      ko.utils.registerEventHandler(element, "changeDate", function(event) {
             var value = valueAccessor();
             if (ko.isObservable(value)) {
                 value(event.date);
             }                
      });
    },
    update: function(element, valueAccessor)   {
        var widget = $(element).data("datepicker");
         //when the view model is updated, update the widget
        if (widget) {
            widget.date = ko.utils.unwrapObservable(valueAccessor());
            if (widget.date) {
                widget.setValue();            
            }
        }
    }
};

Не было похоже, что есть какая-либо функция уничтожения, поэтому я удалил эту часть. Это обрабатывает событие widgets changeDate для обновления модели представления, когда пользователь меняет дату. Функция update обрабатывается при изменении модели представления для обновления виджета.

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

http://jsfiddle.net/rniemeyer/KLpq7/

Ответ 2

моя текущая версия представляет собой смесь между уже показанными решениями:

ko.bindingHandlers.datepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {

    var unwrap = ko.utils.unwrapObservable;
    var dataSource = valueAccessor();
    var binding = allBindingsAccessor();

    //initialize datepicker with some optional options
    var options = allBindingsAccessor().datepickerOptions || {};
    $(element).datepicker(options);
    $(element).datepicker('update', dataSource());
    //when a user changes the date, update the view model
    ko.utils.registerEventHandler(element, "changeDate", function (event) {
        var value = valueAccessor();
        if (ko.isObservable(value)) {
            value(event.date);
        }
    });
},
update: function (element, valueAccessor) {
    var widget = $(element).data("datepicker");

    var value = ko.utils.unwrapObservable(valueAccessor());

    //when the view model is updated, update the widget
    if (widget) {
        widget.date = value;
        if (widget.date) {
            widget.setValue();
            $(element).datepicker('update', value)
        }
    }
}};

Ответ 3

Принятый ответ не работал у меня с текущей версией выбора даты. Вход не инициализировался со значением наблюдаемого. Я сделал обновленную привязку, к которой добавил:

$(element).datepicker('update', dataSource());

Это похоже на трюк.

Здесь обновленная скрипта, в которой используется последний доступный выбор даты, Bootstrap, jQuery и Knockout: http://jsfiddle.net/krainey/nxhqerxg/

Update:

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

Если пользователь попытался отредактировать 10/07/2014, например, и использовал backspace или delete, чтобы удалить номер (10/0/2014), результирующее значение будет немедленно проанализировано и вставлено в текстовый ввод. Если бы значение было на мгновение 10/0/2014, сборщик перенесет календарь на 30.09.2014 и включит это значение в текстовое поле. Если бы я попытался отредактировать месяц, и значение было, на мгновение, 1/7/2014, сборщик переместился бы на 7 января 2014 года и включил это значение в текстовое поле.

Вы можете увидеть это поведение в этой скрипте:

http://jsfiddle.net/krainey/nxhqerxg/10/

Мне пришлось обновить привязку специальным обработчиком для обнаружения фокуса и связать одноразовое событие размытия, чтобы оно правильно обрабатывало ручные изменения.

$(element).on("changeDate", function (ev) {
    var observable = valueAccessor();
    if ($(element).is(':focus')) {
        // Don't update while the user is in the field...
        // Instead, handle focus loss
        $(element).one('blur', function(ev){
            var dateVal = $(element).datepicker("getDate");
            observable(dateVal);
        });
    }
    else {
        observable(ev.date);
    }
});

Сценарий, указанный в исходном ответе, был обновлен, чтобы отразить это:

http://jsfiddle.net/krainey/nxhqerxg/

Ответ 4

Вот что я закончил

ko.bindingHandlers.datepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
    //initialize datepicker with some optional options

    var options = {
        autoclose: true,
        format: 'yyyy-mm-dd',
    }

    //var options = allBindingsAccessor().datepickerOptions || {};
    $(element).datepicker(options);

    //when a user changes the date, update the view model
    ko.utils.registerEventHandler(element, "changeDate", function (event) {
        var value = valueAccessor();

        if (ko.isObservable(value)) {
            var myDate = event.date;
            var month = myDate.getMonth() + 1;
            var monthText = month;

            if (month < 10)
                monthText = "0" + month;

            var day1 = parseInt(myDate.getDate());
            var dayText = day1;

            if (day1 < 10)
                dayText = '0' + day1;

            value(myDate.getFullYear() + '-' + monthText + '-' + dayText);
        }
    });
},
update: function (element, valueAccessor) {

    var widget = $(element).data("datepicker");
    //when the view model is updated, update the widget
    if (widget) {
        widget.date = ko.utils.unwrapObservable(valueAccessor());
        widget.setValue(widget.date);
    }
}};