过滤表内容

Mar*_* C. 3 knockout.js

我希望实现一个绑定来搜索HTML表.

我考虑过实现一个自定义绑定并利用jQuery进行繁重的工作.自定义绑定方面是使其在我的解决方案中普遍可访问.我目前的解决方案仅包含jQuery,并且不使用任何KnockoutJS功能.

问题:如何传入要搜索的"目标"表?ko.customBindings只能访问它绑定的元素,我需要使用输入,所以我不知道是否有办法覆盖参数并传入id表的目标或其他东西.获取搜索词很容易通过valueAccessor,但我不知道我是否可以使用

同样,我想让这个功能"提升和移动",所以如果有一个更好的通用方法来解决这个问题,我当然不会意识到这一点,也没有发现它寻找解决方案.我假设a customBinding是一个很好的解决方案,因为我已经看到它被如何使用,但不会反对其他解决方案.

我想的是:

ko.bindingHandlers.searchTable = {
    update: function(element, valueAccessor, tableIdToSearch) {
        var term = ko.unwrap(valueAccessor());        
        //check if table exists
        // $.each(tableIdToSearch).find("tr"), function() .. use term
    }  
};
Run Code Online (Sandbox Code Playgroud)

Jer*_*oen 7

通常使用Knockout和MVVM模式,保持View"哑"通常是明智的,仅仅反映(或修改,使用双向绑定)ViewModel的当前状态.

我不是100%肯定"搜索HTML表格"的意思,但搜索表格数据本身对我来说更有意义.对于中小型案例,computed可观察数组可以为您完成工作,如下所示:

var ViewModel = function() {
  var self = this;
  
  self.filter = ko.observable('');
  
  self.items = ko.observableArray(["apples", "apple pie", "apple sauce", "pumpkin pie", "peaches"]);
  
  self.filteredItems = ko.computed(function() {
    var filter = self.filter();
    if (!filter) { return self.items(); }
    return self.items().filter(function(i) { return i.indexOf(filter) > -1; });
  });
};

ko.applyBindings(new ViewModel());
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
Search: <input data-bind="textInput: filter" />
<table>
  <tbody data-bind="foreach: filteredItems">
    <tr><td data-bind="text: $data"></td></tr>
  </tbody>
</table>
Run Code Online (Sandbox Code Playgroud)

显然有一些细节需要解决(区分大小写,节流等),但总体思路是存在的.有很多不同的方法可以提高性能,但首先要检查你是否要这样做; 不要太早优化!您尚未在性能问题中指定任何实际标准,因此尝试此方法是您最好的选择.

这也可能是"Knockout/MVVM"风格解决方案.我发现你通常会得到最干净的代码如果你只使用jQuery,如果你也使用Knockout ......


如果你确实想要实际搜索"HTML表",即过滤掉不是由Knockout生成的DOM,但仍然使用自定义绑定,那可能的.以下是一个示例方法:

ko.bindingHandlers["filterTable"] = {
  init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {

  },
  update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    var filter = ko.utils.unwrapObservable(valueAccessor());
    
    $(element).find('tr').each(function(index, row) {
      if ($(row).find('td:contains("'+filter+'")').length > 0) {
        $(row).show();
      }
      else {
        $(row).hide();
      }
    });
  }
};

$(function() {
  var ViewModel = function() {
    var self = this;
    
    self.filter = ko.observable('');
  };
  
  var items = ["apples", "apple pie", "apple sauce", "pumpkin pie", "peaches"];
  
  ko.applyBindings(new ViewModel());  
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

Search: <input data-bind="textInput: filter" />
<table data-bind="filterTable: filter">
  <tbody>
    <tr><td>apples</td></tr>
    <tr><td>apple pie</td></tr>
    <tr><td>apple sauce</td></tr>
    <tr><td>pumpkin pie</td></tr>
    <tr><td>peaches</td></tr>
  </tbody>
</table>
Run Code Online (Sandbox Code Playgroud)

同样,还有很多细节需要解决(区分大小写和其他过滤细节),但我不能提出更具体的建议,因为你没有在你的问题中提供任何细节.您必须根据自己的情况调整上述解决方案.

我的例子使用showhide,而是一个"升降机及移动"解决方案,您帕克说tr在不同的隐藏的表元素来完成工作在这里很好,因为淘汰赛是不是在控制tableDOM.