【问题标题】:Filtering an observableArray in Knockout在 Knockout 中过滤 observableArray
【发布时间】:2014-04-20 12:50:48
【问题描述】:

我坚持在 Knockout 中过滤 observableArray。我正在显示人员列表,并希望有一个复选框列表,该列表可以根据选中的复选框实时更新人员列表(例如:年龄:18 -22、23-30、31-36 等。 )

I read Ryan Niemeyer's 关于实用函数的文章,但我仍然很困惑。我不知道如何用过滤后的项目更新可观察数组。

我正在使用 DurandalDozerJS,这是我目前拥有的标记和 shell 文件

<section class="main">
  <div class="main--contain">
    <a data-bind="click: find25to35">Between 25 and 35</a>

    <form>
        <input type="search" name="search" placeholder="Search" class="search-input">
    </form>

    <ul class="user-list" data-bind="foreach: people">
        <li>
            <h2 data-bind="text: username"></h2>
            <h2 data-bind="text: firstname + lastname"></h2>
        </li>
    </ul>
</div>

define(['knockout'], function (ko) {

  var ctor = {
    people: ko.observableArray(),

    activate: function () {
      var self = this;

      var request = $.ajax({
        url: '/api/users/',
        type: 'GET'
      });

      request.done(function (res) {
        if (res.data.length) {
          res.data.reverse();
          for (var i = 0, z = res.data.length; i < z; i++) {
            self.people.push(res.data[i])
          }
        }
      })
    },

    find25to35: function () {
      var self = this;

      self.people = [];

      ko.utils.arrayForEach(self.people(), function(person) {
        if (person.age >=18 && person.age <=25) {
          self.people.push(person);
        }
      });
}
  };

  return ctor;

});

【问题讨论】:

  • 我没有看到您在标记中提到的复选框,也没有看到基于检查输入进行过滤的计算 observable。我假设过滤是基于本地数据的,对吧?或者您要返回服务器获取过滤后的人员。
  • 这似乎也不是一个合适的绑定:

    。我会创建一个 Person 对象并有一个计算的 observable 来连接名字和姓氏。
  • @Hernan 我更新了这个问题。添加了一个锚点(暂时代替复选框),以及一个 find25to35 函数,该函数使用 arrayForEach 遍历 people 数组,并且应该只使用 18 到 25 岁的人更新该数组. 当然,它不起作用:/我可以让它添加到该数组中,但它不会过滤它们,它只是添加 DOM 中的任何内容(如果我删除了我尝试的 self.people = []; 行清除数组...

标签: javascript knockout.js filtering durandal


【解决方案1】:

以下行将不起作用...

<h2 data-bind="text: firstname + lastname"></h2>

淘汰赛很聪明,但没那么聪明。您需要像这样向您的人员视图模型添加一个计算的 observable...

function Person(person) {
    var self = this;

    self.username = ko.observable(person.userName);
    self.firstname = ko.observable(person.firstName);
    self.lastname = ko.observable(person.lastName);
    self.age = ko.observable(person.age);
    self.name = ko.computed(function () {
        return self.firstname() + self.lastname();
    });
}

这会将您的绑定更改为...

<ul class="user-list" data-bind="foreach: people">
    <li>
        <h2 data-bind="text: username"></h2>
        <h2 data-bind="text: name"></h2>
    </li>
</ul>

然后您可能想要添加一个过滤的人员列表,该列表加载所有符合条件的人,首先从所有人开始,然后将其清除并重新加载符合您条件的人。如果有人想通过一套新的标准来找人怎么办?你真的想再次调用 AJAX 来获取所有人吗?我的经验是,除非您正在运行复杂的自定义搜索,否则最好只获取一次数据并让用户对其进行操作。这意味着您最终会得到一个类似于此的数组...

filteredPeople: ko.observableArray([]),

// -- your other relevant code goes here ---

find25to35: function () {
  var self = this;

  // set how many people are currently in array
  var count = filteredPeople().length;

  // loop through array to get rid of all elements to clear it,
  // making sure we're not modifying the collection as we are 
  // iterating through it which creates pointer errors
  for (var i = 0; i < count; i++) {
      filteredPeople().pop();
  }

  ko.utils.arrayForEach(self.people(), function(person) {
      if (person.age() >= 25 || person.age() <= 35) {
          filteredPeople.push(person);
      }
  });
}

不要忘记 Knockout 可观察对象上的括号,因为这些可观察对象实际上是返回对象的方法,并且您希望它们返回您放入其中的内容,而不是用于跟踪其当前值的缩小(或完整)方法这将导致Undefined 错误。哦,当您应用绑定时,为了安全起见,由于您使用的是顶级函数,因此您可能应该像这样添加对它的引用...

<a data-bind="click: $root.find25to35">Between 25 and 35</a>

您的人员列表的绑定会更改以反映过滤...

<ul class="user-list" data-bind="foreach: filteredPeople">

最后,考虑使函数更加动态,以便能够将其重用于其他搜索条件,否则您将违反DRY principle。考虑以下...

<a data-bind="click: $root.findByAge($data, minAge, maxAge)">Find By Age</a>

... 并从那里开始使您的输入具有功能性和可重用性。请记住,如果您使用 jQuery 来获取它们的值,它们不需要在表单中。

编辑注释: 意识到我忘记清除正确的 observable 并且没有注意到导致所有麻烦的方法中的年龄已关闭。代码已修复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-26
    • 1970-01-01
    • 1970-01-01
    • 2013-11-29
    • 1970-01-01
    • 2014-07-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多