我被困在过滤Knockout中的observableArray。我显示了一个人员列表,并希望有一个复选框列表,根据选中的复选框实时更新人员列表(例如:年龄:18 -22,23-30,31-36,等)
I read Ryan Niemeyer's关于效用函数的文章,但我仍然陷入困境。我不知道如何使用随后过滤的项目更新可观察数组。
我正在使用Durandal和DozerJS以及我目前拥有的标记和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;
});
答案 0 :(得分:2)
以下行无效......
<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 observables上的那些括号,因为那些observables实际上是返回一个对象的方法,你希望它们返回你放入它们的内容,而不是用于跟踪它们当前值的缩小(或完整)方法这将导致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来获取它们的值,它们不需要处于某种形式。
编辑注意事项:意识到我忘了清除正确的观察结果,并没有注意到该方法中的年龄已经关闭导致所有麻烦。代码已修复。