knockout.js中有多个过滤器

时间:2014-03-02 15:25:32

标签: javascript knockout.js filtering knockout-2.0

假设我有电影阵列,如果我想按类型过滤我可以做这样的事情

filtered = ko.computed(function() {
        var self = this;

        if ( ! self.genresFilter() || self.genresFilter() === 'all') {
            return this.sourceItems();
        } else {
            return ko.utils.arrayFilter(self.sourceItems(), function(item) {
                return app.utils.inArray(item.genre, self.genresFilter());     
            });
        }
    }, app.viewModels.games);

但是我现在被困的地方是如果我有流派,语言和长度html下拉菜单如何通过全部或部分过滤器有效地过滤电影,这样我就可以拥有90分钟的俄罗斯动作片或动作片长度等?

3 个答案:

答案 0 :(得分:2)

您需要根据提供的每个过滤器逐步构建过滤列表。至于过滤器本身,它们应该由observableArray中的一个observable或全部表示。这很重要,因为它会在您更改过滤器时触发计算更新。

示例:

var filteredList = ko.computed({
    var currentList = this.sourceItems();
    var currentFilters = this.genresFilters();

    ko.utils.arrayForEach(currentFilters, function () {
        currentList = ko.utils.arrayFilter(currentList, function(filter) {
            return app.utils.inArray(filter, currentFilters);     
        });
    });

    return currentList;
});

此代码将遍历每个过滤器,获取最新的过滤列表,并仅保留满足所有条件的项目。

答案 1 :(得分:0)

过滤结果是针对值的组合,可以通过迭代所有可能的过滤器,应用用户选择的过滤器,并从结果中删除不适合过滤器的项目来完成。应用过滤器的顺序无关紧要。这些项目必须符合所有条件才能成为有效结果,因此您可以在不合适的情况下立即将它们丢弃。

这是一些伪代码。

# item1:
# color: red
# price: 5
# language: EN

# item2:
# color: red
# price: 10
# language: RU

# item3:
# color: green
# price: 7
# language: DE


@items = ( item1, item2, item3 );
foreach filter in @selectedFilters {
  foreach item in @items {
    delete item from @items if filter.value != item.<filter.type>
    # or <, >, whatever
  }
}

return @items

答案 2 :(得分:0)

我知道这是个老话题,但是最近我遇到了同样的问题,这是针对您的电影模型修改的解决方案。您也可以在这里查看:jsfiddle

var MoviesModel = function(data) {
  var self = this;
  self.Genres = ko.observableArray(data.genres);
  self.Genres.unshift("All");
  self.filterGenre = ko.observable("All");

  self.Languages = ko.observableArray(data.languages);
  self.Languages.unshift("All");
  self.filterLanguage = ko.observable("All");

  self.Lengths = ko.observableArray(data.lengths);
  self.Lengths.unshift("All");
  self.filterLength = ko.observable("All");

  self.movies = ko.observableArray(data.movies);

  self.filteredMovies = ko.computed(function() {
    var filteredArray = ko.utils.arrayFilter(self.movies(), function(item) {
      return (
        (item.genre == self.filterGenre() || self.filterGenre() == "All") &&
        (item.language == self.filterLanguage() || self.filterLanguage() == "All") &&
        (item.length == self.filterLength() || self.filterLength() == "All")
      );
    });
    return filteredArray;
  });
};
var data = {
  genres: ["Drama", "Horror", "Sci-Fi"],
  languages: ["English", "Russian"],
  lengths: ["100", "120", "140", "160"],
  movies: [
    { name: "Godfather", genre: "Drama", language: "English", length: "160" },
    { name: "The shining", genre: "Horror", language: "English", length: "140"},
    { name: "Stalker", genre: "Sci-Fi", language: "Russian", length: "160" },
    { name: "Alien", genre: "Sci-Fi", language: "English", length: "120" },
    { name: "Russiam ark", genre: "Drama", language: "Russian", length: "100" },
    { name: "Psycho", genre: "Horror", language: "English", length: "120" }
  ]
};

var viewModel = new MoviesModel(data);
ko.applyBindings(viewModel);
table td {
  padding-right: 20px;
}
<table>
      <thead>
        <tr>
          <td>Movie name</td>
          <td>Genre</td>
          <td>Language</td>
          <td>Length</td>
        </tr>
        <tr>
          <td></td>
          <td>
            <select data-bind="options: Genres, value: filterGenre"></select>
          </td>
          <td>
            <select
              data-bind="options: Languages, value: filterLanguage"
            ></select>
          </td>
          <td>
            <select data-bind="options: Lengths, value: filterLength"></select>
          </td>
        </tr>
      </thead>

      <tbody data-bind="foreach: filteredMovies">
        <tr>
          <td data-bind="text: name"></td>
          <td data-bind="text: genre"></td>
          <td data-bind="text: language "></td>
          <td data-bind="text: length"></td>
        </tr>
      </tbody>
 </table>

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>