Нокаут и jQuery Mobile: флажки

#jquery-mobile #knockout.js

#jquery-мобильный #knockout.js

Вопрос:

Я пытаюсь динамически добавлять элементы флажков и меток в документ. Элемент Checkbox имеет атрибут привязки данных Knockout для привязки его значения к наблюдаемому значению в ViewModel. Однако, когда я пытаюсь установить флажки с помощью jQuery Mobile, выполнив

 $('input[type="checkbox"]').checkboxradio();
  

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

Есть ли способ одновременно использовать как стиль jQuery Mobile, так и привязки нокаута?

Я использую jQuery Mobile RC1 и Knockout 1.2.1.

Ответ №1:

Я также столкнулся с этой проблемой. К сожалению, все предложения здесь либо не сработали для меня, либо имели другие проблемы. Итак, я создал простую пользовательскую привязку, которая работает во всех версиях KO (включая последнюю версию v3):

 ko.bindingHandlers.jqmChecked = {
    init: ko.bindingHandlers.checked.init,
    update: function (element, valueAccessor) {
        //KO v3 and previous versions of KO handle this differently
        //KO v3 does not use 'update' for 'checked' binding
        if (ko.bindingHandlers.checked.update) 
            ko.bindingHandlers.checked.update.apply(this, arguments); //for KO < v3, delegate the call
        else 
            ko.utils.unwrapObservable(valueAccessor()); //for KO v3, force a subscription to get further updates

        if ($(element).data("mobile-checkboxradio")) //calling 'refresh' only if already enhanced by JQM
            $(element).checkboxradio('refresh');
    }
};
  

Должен использоваться следующим образом:

 <input type="checkbox" data-bind="jqmChecked: someValue" id="checkbox1"/>
  

Смотрите полный рабочий пример здесь:

http://jsfiddle.net/srgstm/ub6sq/

Ответ №2:

Смотрите: https://gist.github.com/1006808

Затем вы можете сделать что-то вроде следующего:

 var $checkbox = $('input[type="checkbox"]');
$checkbox.checkboxradio();
$checkbox.dataBind({
    your options..
});
  

Надеюсь, это поможет!

Комментарии:

1. Это, вероятно, решило бы мою проблему, но я думаю, что это отчасти противоречит цели Knockout. Причина, по которой я выбрал Knockout, заключалась в том, что вы можете устанавливать привязки исключительно в HTML. Так что, если мне нужно поместить часть логики в HTML, а часть — в JavaScript, я мог бы также использовать другой фреймворк.

Ответ №3:

Существует проблема с использованием нокаутов по умолчанию с проверкой привязки со стилизованными объектами, как это делает jQuery mobile. У него те же проблемы, что и у функций Button / Buttonset в jQueryUI. Над флажком есть метка, указывающая, что происходит, и она не обновляется должным образом с помощью стандартной привязки с проверкой нокаута.

Это обсуждается на http://therunningprogrammer.blogspot.com/2011/10/how-to-use-jquery-uis-button-with.html .

Чтобы использовать knockout непосредственно с этими стилизованными объектами из jQuery Mobile, продемонстрированный код должен быть изменен для обработки другого контекста DOM. Я опубликую обновление кода, когда у меня будет немного свободного времени для этого.

Редактировать

В группах Google — Нокаут luv2hike опубликовал решение. Вы можете увидеть, как это работает на http://jsfiddle.net/luv2hike/nrJBC /. Похоже, это рабочее решение вашей проблемы.

Комментарии:

1. Это хороший совет, но, к сожалению, он не решает мою проблему. По какой-то причине мои атрибуты привязки к данным исчезают после применения к нему функции checkboxradio(), поэтому не имеет значения, привязан ли он к checked или jqmChecked. Мне нужно будет продолжить расследование о том, что вызывает исчезновение.

2. Извините за неправильное прочтение вашего вопроса. После прочтения документов на jquerymobile.com/demos/1.0b1/#/demos/1.0b1/docs/forms / … , я не понимаю, почему вы вручную применяете стиль? Документы подразумевают, что все, что вам нужно сделать, это структурировать html по правилам, а фреймворк сделает все остальное.

3. Извините за поздний ответ. Я добавляю эти элементы управления динамически, поэтому jQuery Mobile уже выполнил свою работу до того, как я добавил эти флажки в документ.

4. На самом деле у меня есть решение для этого. Я примерно через 3-4 недели выпущу некоторые пользовательские привязки, которые будут автоматически вызывать правильные функции jquery mobile. На самом деле, это 3 набора привязок, которые будут использовать один и тот же исходный код под управлением jQueryUI, jquery mobile и ни того, ни другого. Вам просто нужно будет изменить, какие файлы включены.

Ответ №4:

Я создал простую привязку, которая работает с jQuery Mobile 1.2.0 и Knockout 2.2.1 и работает с флажками jQuery Mobile по умолчанию. Эта привязка не зависит от пользовательских значков или стилей CSS jQuery Mobile. Это также позволяет использовать обычную разметку флажков в вашем HTML ( <input type="checkbox" ... /> ) в отличие от использования альтернативного элемента разметки, такого как a div .

Вот в чем проблема: http://jsfiddle.net/thedude458/52baX /

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

Ответ №5:

Вот мой сильно прокомментированный код пользовательского обработчика, который я создал для флажков jQueryMobile:

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

    // set the dom element to a checkbox and initialize it (for jquerymobile)
    var checkbox = $(element);
    checkbox.checkboxradio();
    checkbox.attr('type', 'checkbox');

    // register change event to update the model on changes to the dom
    ko.utils.registerEventHandler(element, "change", function() {
        valueAccessor()(

            // off because it is before the ui has refreshed
            $(this).siblings('label.ui-checkbox-off').length > 0
        );
    });
},
update: function(element, valueAccessor) {

    // update the checked binding, i.e., check or uncheck the checkbox
    ko.bindingHandlers.checked.update(element, valueAccessor)

    // and refresh the element (for jquerymobile)
    var checkbox = $(element);
    checkbox.checkboxradio('refresh')
}
};