2013-01-14 67 views
4

有人可以幫助我嗎?Knockoutjs Array Filter

如何獲得多選列表以擁有獨特的國家?另外,如何根據多選中選擇的項目篩選記錄?

下面是的jsfiddle http://jsfiddle.net/B2xcv/代碼

請幫助。

謝謝。

HTML

<div class='liveExample'> 
    <p style="color:red">How do I make this list unique?</p> 
    <p> 
    <select data-bind="options: people,optionsText: 'country', selectedOptions: selectedCountries" size="5" multiple="true" style="width:150px"></select> 
    </p> 
    <p style="color:red">And how do I filter the records below based on the selected items above? (multiple select)</p> 
    <table style="width:300px"> 
    <thead> 
     <th>Name</th> 
     <th>Location</th> 
    </thead> 
    <tbody data-bind="foreach: people"> 
     <tr> 
      <td> 
       <span data-bind="text: name"> </span> 
      </td> 
      <td> 
       <span data-bind="text: country"> </span> 
      </td> 
     </tr> 
    </tbody> 
    </table> 

</div> 

KnockoutJS

// Define a "Person" class that tracks its own name and children, and has a method to add a new child 
var Person = function(name, country) { 
    this.name = name; 
    this.country = country; 
} 

// The view model is an abstract description of the state of the UI, but without any knowledge of the UI technology (HTML) 
var viewModel = { 
    people: [ 
     new Person("Annabelle", "UK"), 
     new Person("Bertie", "UK"), 
     new Person("Bertie", "USA"), 
     new Person("Ali", "Bangladesh"), 
     new Person("Patel", "India"), 
     new Person("Sweatha", "India"), 
     new Person("Minto", "India"), 
     ], 
    selectedCountries: ko.observableArray() 
}; 

ko.applyBindings(viewModel); 

回答

5

OK-,使這項工作的最簡單的方法是創建變量來表示獨特的國家和人民數組的過濾版本。

如果people是一個可觀察的數組,那麼您可能希望uniqueCountries變量是一個計算值。如果它不可觀察,那麼你可以直接計算它。

這裏有一個例子:

viewModel.uniqueCountries = ko.computed(function() { 
     var people = viewModel.people(), 
      index = {}, 
      uniqueCountries= [], 
      length = people.length, 
      i, country; 

     for (i = 0; i < length; i++) { 
      country = people[i].country;  
      if (!index[country]) { 
       index[country] = true; 
       uniqueCountries.push(country); 
      } 
     } 

     return uniqueCountries; 
}); 

主要的想法是隻取一個遍歷所有的人,並建立了獨特的國家組成的數組。要做到這一點,我只需要使用一個「索引」對象,這樣我就可以輕鬆地檢查我們是否已經包含這個國家(沒有循環到我們正在建立的列表中)。然後,您可以將唯一的國家/地區作爲數組返回並在您的選擇中綁定它。

接下來,您需要創建一個計算的observable來表示people的過濾版本。這裏是一個樣本:

viewModel.filteredPeople = ko.computed(function() { 
    var selected = viewModel.selectedCountries() || [], 
     index = {}; 

    //build an index, so we can avoid looping each time 
    ko.utils.arrayForEach(selected, function(country) { 
     index[country] = true; 
    }); 

    return ko.utils.arrayFilter(viewModel.people(), function(person) { 
     return index[person.country]; 
    }); 
}); 

我再次建立一個索引,因爲你可以選擇多個國家。這可以很容易地檢查這個人的國家是否是所選國家之一。 ko.utils.arrayFilter將讓我們對數組中的每個項目運行一個函數,並返回一個包含函數返回「真值」值的任何項目的新數組。我再次假設people是一個可觀察的數組,您可能會添加/刪除項目。

以下是更新的樣本:http://jsfiddle.net/rniemeyer/xsfRR/

+0

非常感謝您的快速回復。 :) – Huzzi

+1

這個答案與我正在尋找的東西沒有直接關係,但是我僅僅爲答案的純粹質量而努力。做得好! –

+0

@DavidMontgomery I:P –

2

我知道這可能有點晚,但對於有興趣的人我做到了用KO這樣內置函數:在HTML

var viewModel = { 
    people: [ 
     new Person("Annabelle", "UK"), 
     new Person("Bertie", "UK"), 
     new Person("Bertie", "USA"), 
     new Person("Ali", "Bangladesh"), 
     new Person("Patel", "India"), 
     new Person("Sweatha", "India"), 
     new Person("Minto", "India"), 
     ], 
     selectedCountries: ko.observableArray(), 
     uniqueCountries: function(){ 
      var countries =ko.utils.arrayMap(viewModel.people,function(person){ 
       return person.country; 
      }); 
      return ko.utils.arrayGetDistinctValues(countries); 
     }, 
     filteredRecords: function(){ 
      return ko.utils.arrayFilter(viewModel.people,function(person){ 
       return person.country == viewModel.selectedCountries(); 
      }); 
     } 
}; 

ko.applyBindings(viewModel); 

<div class='liveExample'> 
    <p style="color:red">How do I make this list unique?</p> 
    <p> 
    <select data-bind="options: uniqueCountries(), selectedOptions: selectedCountries" size="5" multiple="true" style="width:150px"></select> 
    </p> 
    <p style="color:red">And how do I filter the records below based on the selected items above? (multiple select)</p> 
    <table style="width:300px"> 
    <thead> 
     <th>Name</th> 
     <th>Location</th> 
    </thead> 
    <tbody data-bind="foreach: filteredRecords()"> 
     <tr> 
      <td> 
       <span data-bind="text: name"> </span> 
      </td> 
      <td> 
       <span data-bind="text: country"> </span> 
      </td> 
     </tr> 
    </tbody> 
    </table> 

</div> 

and here in jsfiddle http://jsfiddle.net/geomorillo/n5JFL/1/

0
 self.filterGrid = ko.computed(function() { 
      var text = filter().toLowerCase(); 
      if (!text) { 
       return self.filterArrayCollection(); 
      } 
      else { 
       if (self.filterArrayCollection() != 'undefined' && self.filterArrayCollection() != null && self.filterArrayCollection().length > 0) { 
        return ko.utils.arrayFilter(self.filterArrayCollection(), 
          function (item) { 
           return (item.name.toLowerCase().indexOf(text) > -1 || item.address.toLowerCase().indexOf(text) > -1); 
          }); 
       }; 
      }; 
     });