删除模板时没有丢弃对话框

时间:2015-03-31 01:24:13

标签: jquery-ui knockout.js jquery-ui-dialog

解决方案:http://jsfiddle.net/lookitstony/24hups0e/6/ Crimson的评论引导我找到解决方案。

我遇到KO和Jquery UI对话框的问题。使用加载它们的模板不会破坏对话框。

我以前存储了一个对话框的实例,并在不使用绑定处理程序的情况下反复重复使用它。在阅读了几篇关于包含的绑定处理程序的帖子后,我觉得这可能是处理对话框的最佳方式。我使用淘汰赛错了吗?我应该坚持使用存储的参考文献还是KO有更好的方法来处理这个问题?如果这是一个SPA,如果我在可能有或没有这些对话框的页面之间进行交换,我将如何管理?

您可以在此处查看我的示例来见证此行为:http://jsfiddle.net/lookitstony/24hups0e/2/

JAVASCRIPT

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


$(function () {

    var vm = {
        open: ko.observable(false),
        content: ko.observable('Nothing to see here...'),
        templateOne: ko.observable(true),
        templateTwo: ko.observable(false),

        templateOneHasDialog: ko.observable(true),
        showOne: function(){
            this.templateTwo(false);
            this.templateOne(true);
        },
        showTwo: function(){
            this.templateOne(false);
            this.templateTwo(true);
        },

        diagOpt: {
            autoOpen: false,
            position: "center",
            modal: true,
            draggable: true,
            width: 'auto'
        },
        openDialog: function () {
            if(this.templateOneHasDialog()){            
                this.content('Dialog opened!');
                this.open(open);                
            } else {
                this.content('No Dialog Available');
            }
        }
    }

    ko.applyBindings(vm);
});

HTML

<div id='ContentContainer'>
Experience Multiple Dialogs
    <ul>
        <li>Click "Open Dialog"</li>
        <li>Move the dialog out of the center and notice only 1 dialog</li>
        <li>Close Dialog</li>
        <li>Now click "One" and "Two" buttons back and forth a few times</li>
        <li>Now click "Open Dialog"</li>
        <li>Move the dialog and observe the multiple dialogs</li>        
    </ul>
    <button data-bind="click:showOne">One</button>
    <button data-bind="click:showTwo">Two</button>

    <!-- ko if: templateOne -->
    <div data-bind="template:{name:'template-one'}"></div>
    <!-- /ko -->
    <!-- ko if: templateTwo -->
    <div data-bind="template:{name:'template-two'}"></div>
    <!-- /ko -->
</div>

<script type="text/html" id="template-one">
    <h3>Template #1</h3>
    <p data-bind="text:content"></p>

    <div><input type= "checkbox" data-bind="checked:templateOneHasDialog" /> Has Dialog </div>

    <button data-bind="click:openDialog">Open Dialog</button>

    <!-- ko if: templateOneHasDialog -->
    <div style="display:none" data-bind="dialog:diagOpt, dialogVisible:open">
        The Amazing Dialog!
     </div>
     <!-- /ko -->

</script>

<script type="text/html" id="template-two">
    Template #2
</script>

1 个答案:

答案 0 :(得分:1)

在模板内使用dialog时,每次显示模板时都会调用init方法,因此在您的案例中会出现多个对话框。要解决此问题,请将对话框置于template

之外
<div style="display:none" data-bind="dialog:diagOpt, dialogVisible:open">
    The Amazing Dialog!
 </div>

将其置于模板之外,现在问题将得到解决。

更新了小提琴:Fiddle

修改:我查看了您的代码,发现您的案例中未触发ko.utils.domNodeDisposal.addDisposeCallback。因此,对话框在模板更改时未被销毁,返回时显示多个对话框。

  

但为什么ko.utils.domNodeDisposal.addDisposeCallback没有打电话?

当从DOM中删除模板中的元素(使用自定义绑定呈现)时,将触发ko.utils.domNodeDisposal.addDisposeCallback。但是在你的情况下,对话框元素被附加到body而不是template,因此它没有被触发

<强>解决方案

jquery ui 1.10.0+可以选择使用appendTo选项指定对话框元素的附加位置,我们可以使用它来解决此问题。

 diagOpt: {
        autoOpen: false,
        position: "center",
        modal: true,
        draggable: true,
        width: 'auto',
        appendTo: "#DesiredDivID"
    },

 <script type="text/html" id="template-one">
<h3>Template #1</h3>
<p data-bind="text:content"></p>

<div><input type= "checkbox" data-bind="checked:templateOneHasDialog" /> Has Dialog </div>

<button data-bind="click:openDialog">Open Dialog</button>

<!-- ko if: templateOneHasDialog -->
<div id="DesiredDivID"></div>
<div id="dlg" data-bind="dialog:diagOpt, dialogVisible:open">
    The Amazing Dialog!
 </div>

     <!-- /ko -->

</script>

现在,对话框元素将附加到#DesiredDivID并在模板更改时被销毁。

请参阅更新的小提琴:Updated one-April-1