我试图创建knockoutjs绑定jquery ui对话框,并且不能得到打开的对话框。对话框元素正确创建,但似乎有显示:无调用对话框(‘打开’)不会删除。此外,对dialog(‘isOpen’)的调用返回对话框对象而不是布尔值。
我使用最新的knockoutjs和jquery 1.4.4与jquery ui 1.8.7。我也试过它与jQuery 1.7.1具有相同的结果。这是我的HTML:
<h1 class="header" data-bind="text: label"></h1>
<div id="dialog" data-bind="dialog: {autoOpen: false,title: 'Dialog test'}">foo dialog</div>
<div>
<button id="openbutton" data-bind="dialogcmd: {id: 'dialog'}" >Open</button>
<button id="openbutton" data-bind="dialogcmd: {id: 'dialog',cmd: 'close'}" >Close</button>
</div>
这是javascript:
var jQueryWidget = function(element,valueAccessor,name,constructor) {
var options = ko.utils.unwrapObservable(valueAccessor());
var $element = $(element);
var $widget = $element.data(name) || constructor($element,options);
$element.data(name,$widget);
};
ko.bindingHandlers.dialog = {
init: function(element,allBindingsAccessor,viewmodel) {
jQueryWidget(element,'dialog',function($element,options) {
console.log("Creating dialog on " + $element);
return $element.dialog(options);
});
}
};
ko.bindingHandlers.dialogcmd = {
init: function(element,viewmodel) {
$(element).button().click(function() {
var options = ko.utils.unwrapObservable(valueAccessor());
var $dialog = $('#' + options.id).data('dialog');
var isOpen = $dialog.dialog('isOpen');
console.log("Before command dialog is open: " + isOpen);
$dialog.dialog(options.cmd || 'open');
return false;
});
}
};
var viewmodel = {
label: ko.observable('dialog test')
};
ko.applyBindings(viewmodel);
我设置了一个JSFiddle,再现的问题。
我想知道这是否与knockoutjs和事件处理有关。我试图从点击处理程序返回true,但是这似乎没有影响任何东西。
解决方法
它看起来像写入小部件到.data(“对话框”),然后尝试操作它是导致一个问题。这里是一个不使用.data的示例,并且基于元素:
http://jsfiddle.net/rniemeyer/durKS/调用打开/关闭
或者,我喜欢以稍微不同的方式使用对话框。我喜欢通过使用observable来控制对话框是打开还是关闭。因此,您将在对话框本身上使用单个绑定。 init将初始化对话框,而更新将检查一个observable,看它是否应该调用open或close。现在,打开/关闭按钮只需要切换一个boolean observable,而不是担心id或查找实际的对话框。
ko.bindingHandlers.dialog = {
init: function(element,allBindingsAccessor) {
var options = ko.utils.unwrapObservable(valueAccessor()) || {};
//do in a setTimeout,so the applyBindings doesn't bind twice from element being copied and moved to bottom
setTimeout(function() {
options.close = function() {
allBindingsAccessor().dialogVisible(false);
};
$(element).dialog(options);
},0);
//handle disposal (not strictly necessary in this scenario)
ko.utils.domNodedisposal.adddisposeCallback(element,function() {
$(element).dialog("destroy");
});
},update: function(element,allBindingsAccessor) {
var shouldBeOpen = ko.utils.unwrapObservable(allBindingsAccessor().dialogVisible),$el = $(element),dialog = $el.data("uiDialog") || $el.data("dialog");
//don't call open/close before initilization
if (dialog) {
$el.dialog(shouldBeOpen ? "open" : "close");
}
}
};
使用方式:
<div id="dialog" data-bind="dialog: {autoOpen: false,title: 'Dialog test' },dialogVisible: isOpen">foo dialog</div>
这里是一个示例:
http://jsfiddle.net/rniemeyer/SnPdE/