将 jquery ui 对话框与 knockoutjs 集成
我正在尝试为 jquery ui 对话框创建 knockoutjs 绑定,但无法打开对话框。对话框元素已正确创建,但似乎有 display: none
,调用 dialog('open')
不会删除。此外,对 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, valueAccessor, allBindingsAccessor, viewModel) {
jQueryWidget(element, valueAccessor, 'dialog', function($element, options) {
console.log("Creating dialog on " + $element);
return $element.dialog(options);
});
}
};
ko.bindingHandlers.dialogcmd = {
init: function(element, valueAccessor, allBindingsAccessor, 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
,但这似乎没有影响任何内容。
I am trying to create knockoutjs bindings for jquery ui dialogs, and cannot get the dialog to open. The dialog element is created correctly, but seems to have display: none
that calling dialog('open')
doesn't remove. Also, the call to dialog('isOpen')
returns the dialog object rather than a boolean.
I am using the latest knockoutjs and jquery 1.4.4 with jquery ui 1.8.7. I've also tried it with jQuery 1.7.1 with the same results. Here's my 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>
and this is the 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, valueAccessor, allBindingsAccessor, viewModel) {
jQueryWidget(element, valueAccessor, 'dialog', function($element, options) {
console.log("Creating dialog on " + $element);
return $element.dialog(options);
});
}
};
ko.bindingHandlers.dialogcmd = {
init: function(element, valueAccessor, allBindingsAccessor, 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);
I have set up a JSFiddle that reproduces the problem.
I am wondering if this has something to do with knockoutjs and event handling. I tried returning true
from the click handler, but that did not appear to affect anything.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
看起来像将小部件写入 .data("dialog") 然后尝试对其进行操作会导致问题。以下是一个示例,其中未使用
.data
,并且根据元素调用打开/关闭:http: //jsfiddle.net/rniemeyer/durKS/另外,我喜欢以稍微不同的方式使用对话框。我喜欢使用可观察对象来控制对话框是打开还是关闭。因此,您可以在对话框本身上使用单个绑定。
init
将初始化对话框,而update
将检查可观察对象以查看它是否应该调用打开或关闭。现在,打开/关闭按钮只需要切换布尔可观察值,而不用担心 ids 或定位实际的对话框。使用方式如下:
这是一个示例:
http://jsfiddle.net/rniemeyer/SnPdE/
It looks like writing to the widget to .data("dialog") and then trying to operate on it is causing an issue. Here is a sample where
.data
is not used and the open/close is called based on the element: http://jsfiddle.net/rniemeyer/durKS/Alternatively, I like to work with the dialog in a slightly different way. I like to control whether the dialog is open or closed by using an observable. So, you would use a single binding on the dialog itself. The
init
would initialize the dialog, while theupdate
would check an observable to see if it should call open or close. Now, the open/close buttons just need to toggle a boolean observable rather than worry about ids or locating the actual dialog.Used like:
Here is a sample:
http://jsfiddle.net/rniemeyer/SnPdE/
我对 RP Niemeyer 的答案做了一些更改,以允许对话框的选项可观察
http://jsfiddle.net/YmQTW /1/
使用 ko.toJS 获取可观察值以初始化小部件
并在更新时检查可观察值
I made a little change to RP Niemeyer's answer to allow the dialog's options to be observables
http://jsfiddle.net/YmQTW/1/
Get the observables values with ko.toJS to initialize the widget
and check for observables on update
在此处添加此内容是因为这是大多数人在搜索 jQuery UI Dialog 和 Knockout JS 问题时发现的内容。
这是避免上述答案中解释的“双重绑定”问题的另一种选择。对我来说, setTimeout() 导致其他需要初始化对话框的绑定失败。对我有用的简单解决方案是对接受的答案进行以下更改:
使用自定义对话框绑定将 class='dialog' 添加到任何元素。
在页面加载之后、调用 ko.applyBindings() 之前调用此方法:
$('.dialog').dialog({autoOpen: false});
去掉自定义绑定的
init
里面的setTimeout
,直接调用代码即可。步骤 2 确保所有 jQuery UI 对话框都已在任何 KO 绑定之前初始化。这样 jQuery UI 已经移动了 DOM 元素,因此您不必担心它们在 applyBindings 中间移动。初始化代码仍然按原样工作(除了删除 setTimeout 之外),因为dialog()函数只会更新现有的对话框(如果已经初始化)。
我需要这个的一个例子是由于我用来更新对话框标题的自定义绑定:
我为此使用单独的绑定而不是主对话框绑定的更新函数,因为我只想更新标题,不是其他属性,例如高度和宽度(不希望对话框仅仅因为我更改标题而调整大小)。我想我也可以使用更新并仅删除高度/宽度,但现在我可以同时执行两者/任一操作,而不必担心 setTimeout 是否完成。
Adding this here because this is what most people find when searching on issues with jQuery UI Dialog and Knockout JS.
Just another option to avoid the "double binding" issue explained in the above answer. For me, the setTimeout() was causing other bindings to fail that require the dialog to be initialized already. The simple solution that worked for me was making the following changes to the accepted answer:
Add class='dialog' to any elements using the custom dialog binding.
Call this after page load, but before calling ko.applyBindings():
$('.dialog').dialog({autoOpen: false});
Remove the
setTimeout
inside theinit
of the custom binding, and just call the code directly.Step 2 makes sure that any jQuery UI Dialogs have been initialized prior to any KO bindings. This way jQuery UI has already moved the DOM elements, so that you don't have to worry about them moving in the middle of applyBindings. The init code still works as-is (other than removing setTimeout) because the dialog() function will just update an existing dialog if already initialized.
An example of why I needed this is due to a custom binding I use to update the title of the dialog:
I use a separate binding for this instead of the update function for the main dialog binding, because I only want to update the title, not other properties such as height and width (don't want the dialog to resize just because I change the title). I suppose I could also use update and just remove height/width, but now I can do both/either and not worry about the setTimeout being completed or not.
这是出色的 RP Niemeyer 绑定处理程序的变体,对于不同的场景很有用。
要允许实体的版本,您可以创建一个带有版本控件的
,并使用
with
绑定,这取决于专门为实体创建的可观察对象版。例如,要允许编辑
person
,您可以像editedPerson
一样创建和观察,并创建一个带有编辑控件的 div,并使用如下绑定:一个人对可观察者来说就像这样:
绑定使
div
可见。当你完成编辑后,你可以将 observable 设置为 null,就像这样,
div
将关闭。我对 RP Niemeyer 的 bindingHandler 的变体允许在 jQuery UI 对话框中自动显示此 div。要使用它,您只需保留原始
with
绑定,并指定 jQuery UI 对话框选项,如下所示:您可以获取我的绑定处理程序的代码,并在此处查看它的实际操作:
http://jsfiddle.net/jbustos/dBLeg/
您可以轻松修改此代码以使对话框具有不同的默认值,甚至让这些默认情况下,可以通过将处理程序封装在 js 模块中并添加公共配置函数来修改它来进行配置。 (您可以将此函数添加到绑定处理程序中,它将继续工作)。
This is a variation of the great RP Niemeyer binding handler, which is useful for a differente scenario.
To allow the edition of an entity, you can create a
<div>
with edition controls, and use awith
binding, which depends on an observable made on purpose for the edition.For example, to allow the edition of a
person
, you can create and observable likeeditedPerson
, and create a div with edition controls, with a binding like this:When you add a person to the observable lke so:
the binding makes the
div
visible. When you finish the edition, you can set the observable to null, like soand the
div
will close.My variation of RP Niemeyer's bindingHandler allows to automatically show this div inside a jQuery UI dialog. To use it you simply have to keep the original
with
binding, and specify the jQuery UI dialog options like so:You can get the code of my binding handler, and see it in action here:
http://jsfiddle.net/jbustos/dBLeg/
You can modify this code easily to have different defaults for the dialog, and even to make these defaults configurable by enclosing the handler in a js module, and adding a public configuration function to modify it. (You can add this function to the binding handler, and it will keep working).
现在 这个库 包含 KnockoutJS 的所有 JQueryUI 绑定,包括当然,还有对话框小部件。
There's now this library that has all the JQueryUI bindings for KnockoutJS including, of course, the dialog widget.