Knockout - 通过多个对象属性过滤可观察数组中的对象

时间:2014-10-15 03:34:30

标签: javascript arrays knockout.js javascript-objects

所以这就是......我正在尝试使用Knockout.js构建数据网格。我想从头开始构建它(技能构建练习),所以我不想使用KoGrid或SimpleGrid。

我遇到的问题是我希望能够根据文本输入过滤结果。此过滤器必须遍历每个对象,并在 ONLY 上过滤与列的value属性匹配的键。

实施例

  

使用值' 1'进行过滤将返回包含属性为1的数据对象(ID 1和ID 3)。

JSFIDDLE

HTML

<div data-bind="foreach: filteredItems">
    <p data-bind="text: LastName"></p>
</div>
<p>Filter:
    <input data-bind="value: filter, valueUpdate: 'keyup'" />
</p>
<p>Filter Value: <span data-bind="text: filter"></span></p>

的JavaScript

var data = [{
    Id: 1,
    LastName: "Franklin"
}, {
    Id: 2,
    LastName: "Green"
}, {
    Id: 3,
    LastName: "1"
}];

var columns = [{
    value: 'Id'
}, {
    value: 'LastName'
}];

var Filtering = function (data, columns) {
    var self = this;

    self.items = ko.observableArray(data);
    self.columns = ko.observableArray(columns);
    self.filter = ko.observable();

    self.filteredItems = ko.computed(function () {
        var filter = self.filter();
        console.log(filter);
        if (!filter) {
            return self.items();
        } else {
            return ko.utils.arrayFilter(self.items(), function (item) {
                console.log('Filtering on Item');
                ko.utils.arrayForEach(self.columns(), function (c) {
                    var val = item[c.value];
                    if (typeof val === 'number') {
                        val = val.toString();
                    }
                    console.log('Filtering on Column');
                    return val.toLowerCase().indexOf(filter.toLowerCase()) > -1;
                });
            });
        }

    });
};

ko.applyBindings(new Filtering(data, columns));

它可以很好地静态设置c.value中的item[c.value],但是当我尝试循环遍历self.columns()数组时,我不会返回结果。

建议书

我可以使用jQueryKnockout.js 3.0underscore.js

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

您的过滤案例没有返回任何内容。如果项目应包含在结果中,ko.utils.arrayFilter()应返回真值。但是,由于它不返回任何内容,因此结果中不包含任何内容。你需要重写它以便返回一些东西。

我想你可以将内部ko.utils.arrayForEach()调用更改为过滤器,如果结果为非空则返回true。

self.filteredItems = ko.computed(function () {
    var filter = self.filter();
    console.log(filter);
    if (!filter) {
        return self.items();
    } else {
        return ko.utils.arrayFilter(self.items(), function (item) {
            console.log('Filtering on Item');
            var result = ko.utils.arrayFilter(self.columns(), function (c) {
                var val = item[c.value];
                if (typeof val === 'number') {
                    val = val.toString();
                }
                console.log('Filtering on Column');
                return val.toLowerCase().indexOf(filter.toLowerCase()) > -1;
            });
            return !!result.length;
        });
    }
});

答案 1 :(得分:1)

您的代码中只有少数问题:

  • 需要返回布尔值作为ko.utils.arrayFilter
  • 的输出
  • 你需要为arrayForEach总结一下,因为你的过滤器是OR

我更改了您的代码以解决这些问题:

var Filtering = function (data, columns) {
    var self = this;

    self.items = ko.observableArray(data);
    self.columns = ko.observableArray(columns);
    self.filter = ko.observable();

    self.filteredItems = ko.computed(function () {
        var filter = self.filter();
        console.log(filter);
        if (!filter) {
            return self.items();
        } else {
            return ko.utils.arrayFilter(self.items(), function (item) {
                console.log('Filtering on Item');
                var matching = -1;
                ko.utils.arrayForEach(self.columns(), function (c) {
                    var val = item[c.value];
                    if (typeof val === 'number') {
                        val = val.toString();
                    }
                    console.log('Filtering on Column');
                    matching+= val.toLowerCase().indexOf(filter.toLowerCase())+1;
                });
                 console.log(matching);
                return matching>=0;
            });
        }

    });
};

在那里为我工作:http://jsfiddle.net/Lzud7fjr/1/