我试图创建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>