2015-03-31 102 views
-1

解決方案如下: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> 
+0

組件綁定將簡化所有這些。 – CrimsonChris 2015-03-31 02:58:41

+0

@CrimsonChris,我希望我可以說你的評論幫助。我已經查看了組件,但它們看起來像模板/視圖模型上的一個花哨層。你能詳細闡述一下這將如何幫助或提供一個例子來清楚地表明? – Tony 2015-03-31 14:47:53

+0

組件綁定可以是動態的。您可以製作一堆對話框組件,然後將其名稱之一傳遞給負責顯示對話框組件的「對話層」。 – CrimsonChris 2015-03-31 14:51:35

回答

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

+0

這確實工作,我怎麼會確保對話框與模板雖然?如果另一種開發出現在我身後,需要重新使用需要對話的頁面,並且沒有意識到存在直接相關的對話框會怎麼樣? – Tony 2015-03-31 14:13:32

+0

我在實際的應用程序中也遇到問題,因爲它將對話框中的模板數據移出。 – Tony 2015-03-31 14:46:33

+0

謝謝你爲什麼對話不會消失,它不再居中,但這正是我所尋找的。 – Tony 2015-04-02 20:15:23