我尝试使用Knockout向我的页面添加复选框。
但是,通过单击它们无法检查那些动态添加的复选框。
如果我使用jQuery添加一个框,则生成的HTML与Knockout复选框不同。 input
包含在另一个<div class="ui-checkbox">
中。
如果未使用自定义绑定checkbox
,也没有区别。
有人知道如何解决这个问题吗?
这是一个小提琴: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"> </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"> </span>
</span>
</label>
<input type="checkbox">
</div>
</div>
答案 0 :(得分:2)
以下是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');
}
答案 1 :(得分: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/