最近做了一个后台系统,用到jquery-easyui作为组件库,虽然好用,但是不能完美的与knockoutjs做结合,这里通过ko.bindingHandlers来自定义方法。
这个是easyui中menu的初始化方法,这里我在onClick的时候把name的值赋给了viewmodel中的name属性。
HTML代码:这里我把name属性使用用viewmodel中的typeName,注意这里typeName是一个方法,因为ko的viewmodel中的属性都是方法(这个有点不习惯)
<div class="form-group">
<label>账号:</label>
<div id="user_menu" data-bind="komenu:{width:200,name:typeName}">
<div data-options="name:'uid'">用户ID</div>
<div data-options="name:'nickname'">用户昵称</div>
</div>
<input class="form-control"
data-bind="kosearchbox:{ text:searchText, width:200,menu:'#user_menu'}" />
</div>
ko的扩展方法:当menu点击的时候,其实是改变了viewmodel中typeName的值。
ko.bindingHandlers.komenu = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var value = valueAccessor();
element = $(element);
var menu = element.menu(_.extend(value, {
onClick: function (item) {
value.hasOwnProperty("name") && value.name(item.name);
}
}));
menu.children("div.menu-item:first").click();
}
};
效果如下:
这样的话,menu的修改会直接体现在viewmodel里面,为后面的combogrid的搜索做基础。
其他的easyui组件也可以做同样的设置,来支持knockout的绑定。下面列举一些常用的。有些只做了单向的绑定。
//渐隐效果
ko.bindingHandlers.slideVisible = {
update: function (element, valueAccessor, allBindingsAccessor) {
// First get the latest data that we're bound to
var value = valueAccessor(), allBindings = allBindingsAccessor();
// Next, whether or not the supplied model property is observable, get its current value
var valueUnwrapped = ko.utils.unwrapObservable(value);
// Grab some more data from another binding property
var duration = allBindings.slideDuration || 400;
// 400ms is default duration unless otherwise specified
// Now manipulate the DOM element
if (valueUnwrapped == true)
$(element).slideDown(duration); // Make the element visible
else
$(element).slideUp(duration); // Make the element invisible
}
};
//menu
ko.bindingHandlers.komenu = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var value = valueAccessor();
element = $(element);
var menu = element.menu(_.extend(value, {
onClick: function (item) {
value.hasOwnProperty("name") && value.name(item.name);
}
}));
menu.children("div.menu-item:first").click();
}
};
//combogrid
ko.bindingHandlers.kocombogrid = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var value = valueAccessor();
element = $(element);
element.combogrid(_.extend({}, value, {
idField: 'id',
textField: 'text',
onSelect: function (rowIndex, rowData) {
var opts = element.combogrid("options");
value.hasOwnProperty("id") && value.id(rowData[opts.valueField || opts.idField]);
},
onChange: function (newValue, oldValue) {
if (!newValue) {
value.hasOwnProperty("id") && value.id(null);
}
//console.log(arguments);
},
filter: function (q, row) {
value.hasOwnProperty("id") && value.id(null);
return false;
//var opts = $(this).combogrid('options');
//return row[opts.textField].indexOf(q) == 0;
}
}));
}
};
//searchbox
ko.bindingHandlers.kosearchbox = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var value = valueAccessor();
element = $(element);
element.searchbox(valueAccessor());
element.searchbox("textbox").on("change", function (e) {
value.hasOwnProperty("text") && value.text($(this).val());
});
}
};
//textbox
ko.bindingHandlers.kotextbox = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var value = valueAccessor();
element = $(element);
element.textbox(_.extend({}, value, {
onChange: function (newValue, oldValue) {
value.hasOwnProperty("text") && value.text(newValue);
}
}));
if (value.hasOwnProperty("emotion") && value.emotion) {
element.textbox("textbox").attr("id", "saytext" + emotionCount).on("changeemotion", function (e) {
element.textbox("setText", $(this).val());
$(this).focus();
});
var $emotion = $("<a style='display:block;margin-top:2px;' href='#'>表情</a>");
element.parent().append($emotion);
$emotion.qqFace({
id: 'emotion' + emotionCount,
assign: 'saytext' + emotionCount,
path: requirejs.toUrl("../../contents/arclist")
});
$emotion.linkbutton({
width: 60
});
emotionCount++;
}
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var value = valueAccessor();
element = $(element);
value.hasOwnProperty("text") && value.text() && element.textbox("setText", value.text());
}
};
//combobox
ko.bindingHandlers.kocombobox = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var value = valueAccessor();
element = $(element);
element.combobox(_.extend({}, value, {
//value: (value && value.hasOwnProperty("id") && value.id()) || null,
onSelect: function (record) {
value && value.hasOwnProperty("id") && value.id(record.value);
}
}));
element.combobox("setValue", (value && value.hasOwnProperty("id") && value.id()) || null);
}
};