2013-09-22 46 views
2

我嘗試使用Knockout將複選框添加到我的頁面。 但是那些動態添加的複選框不能通過點擊來檢查。 如果我使用jQuery添加一個框,生成的HTML與Knockout複選框不同。 input被另一個<div class="ui-checkbox">包裹。 如果不使用自定義綁定checkbox也沒有區別。 有人知道如何解決這個問題嗎?無法檢查通過Knockout動態添加的jQuery-Mobile複選框

  • 的jQuery:1.10.2
  • jQuery的手機: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> 

J S:

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> 
+0

對於初學者,你有幾個我在那裏清理過的語法問題。他們可能沒有破壞任何東西,但他們沒有幫助。我不太明白jQuery手機用第二個複選框試圖做什麼,除了可能有一個隱藏的表示jQuery手機正在創建的假元素,無論哪種方式,我沒有使用它足以幫助進一步,但也許有人可以使用這有助於回答http://jsfiddle.net/USpX5/1/ –

+0

這個問題,當你添加jqm複選框,然後添加knockout時,它會打破之前添加的jqm的結構。我不是一個淘汰賽專家,但它似乎是一個常見問題。我發現很多帖子沒有明確的答案。 – Omar

+0

我找到了解決方案並將其添加爲答案。 – r15ch13

回答

1

我看着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> 

而在BindingHandlers init方法,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/

2

這是Knocko更新的小提琴ut 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'); 
}