【问题标题】:jQuery-Mobile checkboxes dynamically added through Knockout can't be checked无法选中通过 Knockout 动态添加的 jQuery-Mobile 复选框
【发布时间】:2013-09-27 12:06:52
【问题描述】:

我尝试使用 Knockout 在我的页面中添加复选框。 但是那些动态添加的复选框不能通过点击它们来检查。 如果我使用 jQuery 添加一个框,则生成的 HTML 与 Knockout 复选框不同。 input 被包裹在另一个 <div class="ui-checkbox"> 中。 如果不使用自定义绑定checkbox,也没有区别。 有人知道如何解决这个问题吗?

  • jQuery: 1.10.2
  • jQuery-Mobile:1.3.2
  • 淘汰赛:2.3.0

这是一个小提琴:http://jsfiddle.net/USpX5/

HTML:

<div id="fiddle" data-bind="foreach: boxes">
    <label>
        <input type="checkbox" />
        <span data-bind="text: name"></span>
    </label>
</div>

JS:

var BoxModel = function(id, name) {
    this.id = ko.observable(id);
    this.name = ko.observable(name);
};

var MainModel = function()
{
    this.boxes = ko.observableArray([]);
}
var main = new MainModel();

$('#add-ko').click(function() {
    var i = $('#fiddle').find('input[type=checkbox]').length + 1;
    main.boxes.push(new BoxModel('id'+i, 'name'+i));
});
$('#add-jqm').click(function() {
    var i = $('#fiddle').find('input[type=checkbox]').length + 1;
    $('#fiddle').append('<label><input type="checkbox" /><span>name'+i+'</span></label>').trigger('create');
});

// http://stackoverflow.com/a/15841271/2710739
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');
    },
    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');
    }
};

ko.applyBindings(main);

生成的 HTML(从 Chrome DevTools 复制):

<div id="fiddle" data-bind="foreach: boxes">

    <!-- added with ko -->
    <div class="ui-checkbox">
        <label data-corners="true" data-shadow="false" data-iconshadow="true" data-wrapperels="span" data-icon="checkbox-off" data-theme="c" data-mini="false" class="ui-checkbox-off ui-btn ui-btn-corner-all ui-fullsize ui-btn-icon-left ui-btn-up-c">
            <span class="ui-btn-inner">
                <span class="ui-btn-text">
                    <span data-bind="text: name">name1</span>
                </span>
                <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow">&nbsp;</span>
            </span>
        </label>
        <div class="ui-checkbox"><!-- additional ui-checkbox class maybe causes the problem -->
            <input type="checkbox" data-bind="checkbox:true">
        </div>
    </div>

    <!-- added with jqm -->
    <div class="ui-checkbox">
        <label data-corners="true" data-shadow="false" data-iconshadow="true" data-wrapperels="span" data-icon="checkbox-off" data-theme="c" data-mini="false" class="ui-checkbox-off ui-btn ui-btn-corner-all ui-fullsize ui-btn-icon-left ui-btn-up-c">
            <span class="ui-btn-inner">
                <span class="ui-btn-text">
                    <span>name2</span>
                </span>
                <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow">&nbsp;</span>
            </span>
        </label>
        <input type="checkbox">
    </div>
</div>

【问题讨论】:

  • 对于初学者,我在其中清理了一些语法问题。他们可能没有破坏任何东西,但他们没有帮助。我不太明白 jQuery mobile 试图用第二个复选框做什么,除了可能有一个隐藏的复选框来表示 jQuery mobile 正在创建的假元素,无论哪种方式我都没有使用它来提供进一步的帮助,但也许有人可以使用这有助于回答问题jsfiddle.net/USpX5/1
  • 当您添加 jqm 复选框然后添加淘汰赛时,它会破坏先前添加的 jqm 的结构。我不是淘汰专家,但这似乎是一个普遍的问题。我发现很多帖子没有明确的答案。
  • 我找到了解决方案并将其添加为答案。

标签: jquery-mobile knockout.js checkbox


【解决方案1】:

这是 Knockout v3 的更新小提琴:http://jsfiddle.net/USpX5/12/

主要的调整是在绑定的更新方法中。

update: function(element, valueAccessor) {       
    if (ko.bindingHandlers.checked.update) {
         ko.bindingHandlers.checked.update(element, valueAccessor);
    }
    else 
    {
        var value = ko.utils.unwrapObservable(valueAccessor());
        $(element).prop( "checked", value);
    }

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

【讨论】:

    【解决方案2】:

    我再次查看jQuery Mobile Demos 并找到data-role="none"。它可以防止 JQM 自动增强元素。现在我可以添加复选框,然后让 BindingHandler 通过checkbox.checkboxradio() 增强它们。

    现在复选框看起来像这样:

    <button data-bind="click: add">Add checkbox</button>
    
    <!-- show checked boxes -->
    Checked: 
    <div id="checkedBoxes" data-bind="foreach: boxes">
        <span data-bind="text: name, if: checked"></span>
    </div>
    <hr>
    
    <!-- checkboxes -->
    <div id="newBoxes" data-bind="foreach: boxes">
        <label>
            <input type="checkbox" data-bind="checkbox: checked" data-role="none" />
            <span data-bind="text: name"></span>
        </label>
    </div>
    

    而在BindingHandlersinit方法中,checkbox.removeAttr('data-role')用于让JQM通过checkbox.checkboxradio()增强元素:

    ko.bindingHandlers.checkbox = {
        init: function(element, valueAccessor) {    
            // set the dom element to a checkbox and initialize it (for jquerymobile)
            var checkbox = $(element);
            // let jquerymobile enhance the element
            checkbox.removeAttr('data-role');
            // make it so
            checkbox.checkboxradio();
            // register change event to update the model on changes to the dom
            checkbox.on('change', function(e) {
                valueAccessor()(this.checked);
            });
        },
        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');
        }
    };
    
    var BoxModel = function(id, name, checked) {
        var self = this;
        self.id = ko.observable(id);
        self.name = ko.observable(name);
    
        // checkbox state
        self.checked = ko.observable(checked);    
    };
    
    function MainViewModel()
    {
        var self = this;
        // hold all added checkboxes
        self.boxes = ko.observableArray([]);
    
        // add new checkbox
        self.add = function () {
            var i = $('#newBoxes').find('input[type=checkbox]').length + 1;
            self.boxes.push(new BoxModel('id'+i, 'name'+i, false));
        }
    }
    
    ko.applyBindings(new MainViewModel());
    

    这是一个更新的小提琴:http://jsfiddle.net/USpX5/5/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-17
      • 1970-01-01
      • 2010-12-24
      • 1970-01-01
      • 1970-01-01
      • 2013-10-05
      相关资源
      最近更新 更多