2013-10-23 79 views
0

大家好,淘汰賽和JQuery UI定製的結合上觀察到的陣列更新

沒有recoginizing插件我使用Knockoutjs在使用jQuery UI組件聯合使用以顯示與多個跨度爲每個所選項目的自動完成框。

我下面下面的方法

1)在視圖模型具有可觀察到的陣列(selecteditems)並將其綁定到JQUERY UI自動完成構件的輸入框綁定到聲明性模板來顯示跨越

2)以顯示建議,並在每個選擇上使用CustomBindingHandler將新項目添加到selecteditems數組中。

3)使用CustomBindingHandler向每個SPAN顯示綁定到可觀察數組selected items的JQUERY UI ToolTip小部件。

發出─那我面對的是jQuery UI的工具提示部件是顯示了在負載沒有任何問題,但無論何時,只要selecteditems陣列中的改變,工具提示部件沒有在CustomBindingHandler

任何認可非常感謝您的幫助。

<div> 

    <div style="max-height: 105px;" data-bind="foreach: selectedItems"> 

     <span data-bind="text: name, id: id, assignToolTip: id"></span> 

     <input data-bind="assignAutoComplete: { rootVm: $root }" type="email" value=""> 
    </div> 

</div> 

<script> 

    var MyViewModel = function() { 
     this.selectedItems = ko.observableArray(
      [{ name: "eww", id: "ww" }, 
       { name: "aa", id: "vv" }, 
       { name: "xx", id: "zz" }]); 
    }; 

    ko.bindingHandlers.assignToolTip = { 
     init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
      if ($(element) != undefined) { 
       var currentDataItem = ko.dataFor(element); 
       $(element).tooltip({ 
        items: 'span', 
        track: true, 
        content: function() { 

         return "<ul><li>" + currentDataItem.name + "</li><li>" + currentDataItem.id + "</li></ul>"; 
        } 
       }); 
      } 
     }, 

    }; 

    ko.bindingHandlers.assignAutoComplete = { 
     init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
      if ($(element) != undefined) { 
       var currentDataItem = ko.dataFor(element); 
       $(element).autocomplete({ 
        source: function (request, response) { 
         $.ajax({ 
          url: "http://ws.geonames.org/searchJSON", 
          dataType: "jsonp", 
          data: { 
           featureClass: "P", 
           style: "full", 
           maxRows: 12, 
           name_startsWith: request.term 
          }, 
          success: function (data) { 

           response($.map(data.geonames, function (item) { 
            return { 
             label: item.name + (item.adminName1 ? ", " + item.adminName1 : "") + ", " + item.countryName, 
             value: item.name 
            }; 
           })); 
          } 
         }); 
        }, 
        minLength: 2, 
        select: function (event, ui) { 
         var settings = valueAccessor(); 
         var rootVm = settings.rootVm; 
         rootVm.selectedItems.push({ name: ui.item.label, id: ui.item.label }); 
         return false; 
        }, 
        open: function() { 
         $(this).removeClass("ui-corner-all").addClass("ui-corner-top"); 
        }, 
        close: function() { 
         $(this).removeClass("ui-corner-top").addClass("ui-corner-all"); 
        } 
       }); 
      } 
     } 
    }; 


    ko.applyBindings(new MyViewModel()); 
</script> 
<script src="~/Scripts/jquery-ui-1.10.3.js"></script> 

回答

0

如果你想更新提示時,在你的陣列變化值,那麼你就需要改變這個局面了一點,所以您可以在陣列中的對象的值觀察。

var SelectedItem = function(obj){ 
    var self = this; 
    self.name = ko.observable(obj.name); 
    self.id = ko.observable(obj.id); 
    self.tooltipText = ko.computed(function(){ 
     return "<ul><li>" + self.name() + "</li><li>" + self.id() + "</li></ul>"; 
    }); 
    return self; 
}; 

var MyViewModel = function() { 
    var self = this; 
    self.selectedItems = ko.observableArray(
     [new SelectedItem({ name: "eww", id: "ww" }), 
      new SelectedItem({ name: "aa", id: "vv" }), 
      new SelectedItem({ name: "xx", id: "zz" })]); 
    return self; 
}; 

一旦完成,你需要更新customBinding處理更新:

ko.bindingHandlers.assignToolTip = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     if ($(element) != undefined) {     
      var currentDataItem = ko.dataFor(element); 
      $(element).tooltip({ 
       items: 'span', 
       track: true, 
       content: function() { 
        return currentDataItem.tooltipText(); 
       } 
      }); 
     } 
    }, 
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext){    
     if ($(element) != undefined) {     
      $(element).tooltip("destroy"); 
      var currentDataItem = ko.dataFor(element); 
      $(element).tooltip({ 
       items: 'span', 
       track: true, 
       content: function() { 
        return currentDataItem.tooltipText(); 
       } 
      }); 
     } 
    } 
}; 

所需的最後一個變化是,你推入觀察到的陣列任何時候它應該是SelectedItem的一個實例對象:

select: function (event, ui) { 
    var settings = valueAccessor(); 
    var rootVm = settings.rootVm; 
    rootVm.selectedItems.push(
     new SelectedItem({ name: ui.item.label, id: ui.item.label }) 
    ); 
    return false; 
}, 

工作實施例:http://jsfiddle.net/infiniteloops/PLYKk/

+0

爲什麼'if($(element)!= undefined)'?首先,使用'if(element)'更短,不涉及拋出式jQuery調用,但更重要的是:'element'永遠不會被定義。 *(哦,最重要的是,'$(任何))'永遠不會被定義爲開頭,它將始終是一個jQuery對象)* – Tomalak

+0

@Tomalak我沒有試圖編碼審查現有的代碼。當然'如果(元素)'更有意義,但這不是OP的問題。 –

+0

哦,我設法忽略了這是直接來自OP。那麼,假設評論是針對他的,那麼。 :) – Tomalak

0

jQuery UI Tooltip widget的API文檔表明,工具提示邏輯旨在綁定到容器而不是單個元素。

舉例來說,要獲得所有<li>工具提示在<ul>純jQuery的,你可以這樣做:

$("ul").tooltip({ 
    items: "li", 
    content: function() { 
     return "tooltip text for this element"; 
    } 
}); 

的主要優點是,你不需要綁定/解除綁定/更新任何工具提示邏輯,當容器的孩子改變。另一個好處是這會減少頁面上的負載,因爲它只註冊一個工具提示而不是幾個工具提示。


您可以(也應該!)使用這種方法,因爲它完全符合您的要求。你有一個容器,它有一個可變數量的子元素,應該都顯示一個工具提示,其內容按照相同的邏輯構建。

由於我們綁定到容器,我們需要在容器的視圖模型上使用一個小代理函數來爲我們檢索單個工具提示文本。

HTML模板:

<div data-bind=" 
    foreach: items, 
    tooltip: {items: 'label', content: tooltipContentProxy} 
"> 
    <div> 
     <label data-bind="text: name, attr: {for: id}"></label> 
     <input data-bind="attr: {id: id}, value: inputVal, valueUpdate: 'keyup'" type="text" /> 
    </div> 
</div> 

tooltip自定義綁定處理程序:

ko.bindingHandlers.tooltip = { 
    init: function (element, valueAccessor) { 
     var options = ko.unwrap(valueAccessor()); 
     $(element).tooltip(options); 
    } 
}; 

注意我們如何

  • 可以在綁定方便地配置所有的工具提示選項
  • 不會對視圖或視圖模型的任何相關
  • 甚至沒有,因爲這種設置,從任何數據解耦改變

最後我們的視圖模型需要一個update處理器:

function Item(data) { 
    var self = this; 

    self.id = ko.observable(data.id); 
    self.name = ko.observable(data.name); 
    self.inputVal = ko.observable(""); 
    self.tooltipText = ko.computed(function() { 
     var escapedVal = $("<div>", {text: self.inputVal()}).html(); 
     return "Hi! My value is '" + escapedVal + "'."; 
    }); 
} 

function ViewModel() { 
    var self = this; 

    self.items = ko.observableArray([/* Item objects here ...*/]); 

    self.tooltipContentProxy = function() { 
     var targetItem = ko.dataFor(this); 
     return targetItem.tooltipText(); 
    }; 
} 

現在工具提示正確顯示,沒有任何進一步的大驚小怪。 http://jsfiddle.net/7TqpK/