我可能过度思考了这一点,但我想要做的是从绑定到函数的click事件创建一个observableArray。基本上,当我点击一个按钮时,我需要根据event.target.html()
过滤结果,并创建一个可以在页面后面的foreach
循环中使用的observable。
首先,我有一个按钮。
<button data-bind="click: getData">Button Text</button>
根据按钮文字过滤结果的功能
self.filterFunction = function(x) {
// do things here
return (obj);
}
Click绑定到getData
函数,该函数使用点击的DOM元素调用filterFunction
并创建一个可观察的数组
self.getData = function(item, event) {
viewModel.myFilteredData = ko.observableArray(self.filterFunction($(event.target).html()));
}
然后我循环通过myFilteredData
,但失败了。
<!-- ko foreach: myFilteredData -->
// Generate HTML here
<!-- /ko -->
有些东西告诉我,我在逻辑上失败了,并且有一种更有效的方法。我还想找出一种基于某些预设myFilteredData
预先填充Button Text
的方法,这样就可以在点击任何按钮之前在初始页面加载时生成HTML。
谢谢。
答案 0 :(得分:2)
为什么不在视图模型中设置observableArray,创建一个绑定到按钮单击的函数,并传入每个对象?将按钮与每个按钮绑定到一些可观察对象或实体,然后在按钮单击时有一个参数,您可以将其推入observableArray
答案 1 :(得分:2)
也许你遇到的问题是你的foreach
绑定绑定到的是一个不同的可观察数组,而不是你点击后生成的数组。这样想吧。鉴于此视图模型:
{
myFilteredData: ko.observableArray()
}
...当ko.applyBindings
发生时,Knockout订阅此ko.observableArray
以获取更新,并循环遍历(现在为空)数组。
现在,您的点击处理程序发生:
viewModel.myFilteredData = ko.observableArray(self.filterFunction($(event.target).html()));
上面建立的订阅未被触发,因为可观察数组没有改变;相反,你用另一个替换它。不幸的是,Knockout并不知道新的。
我建议您不要使用新数组替换数组,而是使用新数据填充现有数组:
viewModel.myFilteredData(self.filterFunction($(event.target).html()));
答案 2 :(得分:2)
Solefald,肯定有更好的方法来做到这一点。
首先,将您自己的“过滤器”对象的数组添加到视图模型中,以及ko.computed以提供过滤后的数据。将过滤器按钮绑定到“过滤器”对象数组。像这样:
var viewModel = function(){
var self = this;
self.filters = [
{buttonText:'Button Text', filterKey:'filterKeyOne'},
{buttonText:'Other Button Text', filterKey:'filterKeyTwo'}
];
self.selectedFilterKey = ko.observable('none');
self.setFilter = function(){...}
self.data = ko.observableArray([...]);
self.filteredData = ko.computed(function(){...});
}
并像这样绑定:
<div data-bind="foreach: filters">
<button data-bind="click : $parent.setFilter, text: buttonText"></button>
</div>
<div data-bind="foreach: filteredData">
...
</div>
通过让Knockout对过滤器按钮执行单击绑定,您将获得整个过滤器对象作为“runFilter”函数中的第一个参数。然后,您可以实现过滤器按钮单击处理程序(在此示例中为“setFilter”),如下所示:
self.setFilter = function(filterItem){
self.selectedFilterKey(filterItem.filterKey);
};
通过使“selectedFilterKey”成为可观察对象,您可以将filteredData实现为ko.computed,当“selectedFilterKey”发生更改时,它将自动更新ui,如下所示:
...
self.filteredData = ko.computed(function(){
//pick the right filter function
var filterFunction = filterOne;//assign the default filter function
switch(self.selectedFilterKey()){
case 'filterKeyOne':
filterFunction = self.filterOne;//your first filter
break;
case 'filterKeyTwo':
filterFunction = self.filterTwo;//your second filter
break;
}
return ko.utils.arrayFilter(self.data(), function(item){
//return true if item passes filter
return filterFunction(item);
});
});
...
如果您想使用功能更强大的编程方法,请尝试在过滤器对象中定义过滤器函数。
self.filters = [
{buttonText:'Button Text', filterFunction:function(item){...}},
{buttonText:'Other Button Text', filterFunction:function(item){...}}
];
并存储所选的功能,而不是键
self.setFilter = function(filterItem){
self.selectedFilterFunction(filterItem.filterFunction);
};
并跳过switch语句
...
self.filteredData = ko.computed(function(){
return ko.utils.arrayFilter(self.data(), function(item){
//return true if item passes filter
return self.selectedFilterFunction()(item);
});
});
...
如果您想了解有关此排序方法的更多信息,可以在我的博客上阅读:http://ryanrahlf.com/sorting-tables-by-column-header-with-knockout-js/
我希望这有帮助!