将jquery ui对话框与knockoutjs集成 [英] integrating jquery ui dialog with knockoutjs

查看:23
本文介绍了将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'}" >打开</button><button id="openbutton" data-bind="dialogcmd: {id: 'dialog', cmd: 'close'}" >关闭</button>

这是javascript:

var jQueryWidget = function(element, valueAccessor, name, constructor) {var 选项 = ko.utils.unwrapObservable(valueAccessor());var $element = $(element);var $widget = $element.data(name) ||构造函数($元素,选项);$element.data(name, $widget);};ko.bindingHandlers.dialog = {初始化:函数(元素,valueAccessor,allBindingsAccessor,viewModel){jQueryWidget(element, valueAccessor, 'dialog', function($element, options) {console.log("在" + $element 上创建对话框);返回 $element.dialog(options);});}};ko.bindingHandlers.dialogcmd = {初始化:函数(元素,valueAccessor,allBindingsAccessor,viewModel){$(element).button().click(function() {var 选项 = ko.utils.unwrapObservable(valueAccessor());var $dialog = $('#' + options.id).data('dialog');var isOpen = $dialog.dialog('isOpen');console.log("命令对话框打开前:" + isOpen);$dialog.dialog(options.cmd || 'open');返回假;});}};var viewModel = {标签:ko.observable('对话测试')};ko.applyBindings(viewModel);

我已经建立了一个重现问题的 JSFiddle.

我想知道这是否与knockoutjs 和事件处理有关.我尝试从点击处理程序返回 true,但这似乎没有影响任何东西.

解决方案

似乎将小部件写入 .data("dialog") 然后尝试对其进行操作会导致问题.这是一个不使用 .data 并且基于元素调用打开/关闭的示例:http://jsfiddle.net/rniemeyer/durKS/

或者,我喜欢以稍微不同的方式处理对话框.我喜欢通过使用 observable 来控制对话框是打开还是关闭.因此,您将在对话框本身上使用单个绑定.init 将初始化对话框,而 update 将检查一个 observable 以查看它是否应该调用 open 或 close.现在,打开/关闭按钮只需要切换一个布尔值 observable 而不是担心 ids 或定位实际对话框.

ko.bindingHandlers.dialog = {初始化:函数(元素,valueAccessor,allBindingsAccessor){var 选项 = ko.utils.unwrapObservable(valueAccessor()) ||{};//在 setTimeout 中执行,因此 applyBindings 不会从被复制并移动到底部的元素绑定两次设置超时(功能(){options.close = function() {allBindingsAccessor().dialogVisible(false);};$(element).dialog(options);}, 0);//处理处置(在这种情况下不是绝对必要的)ko.utils.domNodeDisposal.addDisposeCallback(元素,函数(){$(element).dialog("销毁");});},更新:函数(元素,valueAccessor,allBindingsAccessor){var shouldBeOpen = ko.utils.unwrapObservable(allBindingsAccessor().dialogVisible),$el = $(元素),dialog = $el.data("uiDialog") ||$el.data("对话框");//在初始化之前不要调用open/close如果(对话框){$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/

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.

解决方案

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 the update 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.

ko.bindingHandlers.dialog = {
        init: function(element, valueAccessor, 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, valueAccessor, 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");
            }  
        }
};

Used like:

<div id="dialog" data-bind="dialog: {autoOpen: false, title: 'Dialog test' }, dialogVisible: isOpen">foo dialog</div>

Here is a sample: http://jsfiddle.net/rniemeyer/SnPdE/

这篇关于将jquery ui对话框与knockoutjs集成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆