将jquery ui对话与knockoutjs集成

Gen*_*sky 37 jquery-ui jquery-ui-dialog knockout.js

我正在尝试为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>
Run Code Online (Sandbox Code Playgroud)

这是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);
Run Code Online (Sandbox Code Playgroud)

我已经设置了一个可以重现问题的JSFiddle.

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

RP *_*yer 64

看起来像是将小部件写入.data("对话框"),然后尝试对其进行操作会导致问题.这是一个.data未使用的示例,并根据元素调用open/close:http: //jsfiddle.net/rniemeyer/durKS/

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

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");
            }  
        }
};
Run Code Online (Sandbox Code Playgroud)

使用如下:

<div id="dialog" data-bind="dialog: {autoOpen: false, title: 'Dialog test' }, dialogVisible: isOpen">foo dialog</div>
Run Code Online (Sandbox Code Playgroud)

以下是一个示例:http: //jsfiddle.net/rniemeyer/SnPdE/

  • 问题是`applyBindings`是从顶部到底部的元素,当`.dialog()`运行时,它实际上将元素移动(并包装)到页面的底部.然后`applyBindings`再次遇到它并再次运行init.setTimeout允许applyBindings在调用`.dialog()`之前完成它在页面中的传递.处置回调可以不进行超时,因为它只会在Knockout清理元素时被调用(比如模板的一部分). (3认同)
  • jquery ui 1.11.3 - 新变化:$(元素).data('ui-dialog').这种对话检测方式经常出现中断,看起来像是非正式的对话检测...... (2认同)

小智 5

我对RP Niemeyer的回答做了一些改动,允许对话框的选项是可观察的

http://jsfiddle.net/YmQTW/1/

使用ko.toJS获取observables值以初始化窗口小部件

setTimeout(function() { 
    options.close = function() {
        allBindingsAccessor().dialogVisible(false);                        
    };

    $(element).dialog(ko.toJS(options));          
}, 0);
Run Code Online (Sandbox Code Playgroud)

并检查更新时的可观察量

//don't call dialog methods before initilization
if (dialog) {
    $el.dialog(shouldBeOpen ? "open" : "close");

    for (var key in options) {
        if (ko.isObservable(options[key])) {
            $el.dialog("option", key, options[key]());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)