我有一个用于绑定到结果表的视图模型。视图动态呈现结果表,而不需要任何先前的列数或名称知识,这很好。与描述here的情况类似,为了保持通用而非特定于域名,我已经根据这些问题回答了代码示例。
但是我需要添加一个过滤器行以允许用户进行过滤,我已根据下面代码中的列名添加了一行输入,并尝试将它们绑定到视图模型。重要的是它们绑定到视图模型,以便在刷新网格时视图模型知道应用的任何过滤器。
我尝试过几件事
任何想法都将不胜感激
非常感谢,Ed
JS
var VM = function () {
var self = this;
self.items = ko.observableArray();
self.filters = ko.observable({});
self.columnNames = ko.computed(function () {
if (self.items().length === 0)
return [];
var props = [];
var obj = self.items()[0];
for (var name in obj)
props.push(name);
return props;
});
};
var vm = new VM();
ko.applyBindings(vm);
vm.items.push({
'Name': 'John',
'Age': 25
});
vm.items.push({
'Name': 'Morgan',
'Age': 26
});
查看:
<table>
<thead>
<tr data-bind="foreach: columnNames">
<th> <span data-bind="text: $data"></span>
</th>
</tr>
</thead>
<tbody >
<!-- add filter rows -->
<tr data-bind="foreach: $root.columnNames">
<td ><input type='text' data-bind="value: $root.filters[$data]"/></td>
</tr>
<!-- add the items -->
<!-- ko foreach: items -->
<tr data-bind="foreach: $parent.columnNames">
<td data-bind="text: $parent[$data]"></td>
</tr>
<!-- /ko -->
</tbody>
</table>
答案 0 :(得分:4)
我做了一个小提琴,其中filters
存储在一个对象{Col1 : Value1, Col2 : Value2...}
中。
现在columnNames
computed返回一个包含列标题及其过滤器的对象。
我还创建了一个计算的filteredItems,它只包含与过滤器匹配的项目。
subscriptions
数组旨在跟踪订阅,以便在列数更改时删除它们。
var VM = function () {
var self = this;
self.items = ko.observableArray();
self.filters = ko.observable({});
self.filteredItems = ko.computed(function () {
var filters = self.filters();
var items = ko.utils.arrayFilter(self.items(), function (item) {
for (var col in filters) {
var v = (item[col] || '').toString(); // cell value
var f = filters[col]; // what you typed in header
if (v.indexOf(f) < 0) return false; // filter is contains
}
return true;
});
return items;
});
var subscriptions = [];
self.columnNames = ko.computed(function () {
// clean old subscriptions
ko.utils.arrayForEach(subscriptions, function (s) { s.dispose(); });
subscriptions = [];
if (self.items().length === 0) return [];
var props = [];
var obj = self.items()[0];
for (var name in obj) {
var p = { name: name, filter: ko.observable('') };
// subscribe : so when you type something, filterOnChanged will be invoked.
subscriptions.push(p.filter.subscribe(filterOnChanged, p));
props.push(p);
}
return props;
});
var filterOnChanged = function (value) {
console.log([this.name, value]);
var filters = self.filters();
filters[this.name] = value;
self.filters(filters);
};
};