我正在研究一个问题/答案模型,我有多个下拉列表包含相同的数据(如果你愿意,还有一组答案)。这里的业务逻辑是,一旦某人选择了问题的答案,该答案只能使用一次而不能用于其他问题。
因此,我找到了一种方法将所有下拉列表绑定到包含我的答案的单个observableArray,以便下拉列表包含相同的选项。我想要做的是订阅一个下拉列表的当前值(在众多下拉列表中),并从与它们相关的所有其他下拉列表中删除所选值。使用Knockout,我已经能够在我的视图中为更改的值订阅回调函数。
在我的回调函数中,我发现使用observableArray的remove
方法从我的observableArray中删除答案是有效的,但不幸的是从所有下拉列表中删除了当前选择的答案 - 包括所选的答案!我已经尝试用推送命令将其恢复,但这也会导致问题。我似乎无法按照我想要的方式隔离更新。
有没有人之前使用Knockout实现过类似的东西?任何帮助或建议将不胜感激。
答案 0 :(得分:4)
因为如果从中删除一个项目,您将被绑定到一个选项数组,那么正确的选项绑定将反映这一点。您可以使用每个要绑定的选择框的计算值创建独立的虚拟列表。
var viewModel = function(data) {
var self = this;
this.values = ko.observableArray([ "option 1", "option 2", "option 3"]);
this.selected = [
new ko.observable(),
new ko.observable(),
new ko.observable()
]
this.remaining = function (current) {
var selected = ko.toJS(self.selected),
currentValue = ko.utils.unwrapObservable(current);
var result = ko.utils.arrayFilter(self.values(), function (option) {
return option == currentValue || selected.indexOf(option) === -1;
});
return result;
};
this.values1 = ko.computed(function () {
return self.remaining(self.selected[0]);
});
this.values2 = ko.computed(function () {
return self.remaining(self.selected[1]);
});
this.values3 = ko.computed(function () {
return self.remaining(self.selected[2]);
});
};
ko.applyBindings(new viewModel());
http://jsfiddle.net/madcapnmckay/6uWEu/2/
修改强>
以上是如何工作的。您需要将每个选择绑定到它自己的observable,以便在您选择第一个值时可以更新其他值。如果您只是简单地绑定到同一个列表并在每次选择值时从中删除,那么您也将删除刚刚选择的值,KO会相应地更新选择元素,它将完全被破坏。
上面的代码通过依次过滤每个代码来解决这个问题。我将每个下拉重定向到它自己的计算可观察量。这些计算出的observable只需调用一个过滤函数,该函数循环遍历values数组,并过滤掉所有已选择的 NOT 当前所选值。
因此,如果我们从所有未选中开始,则第一个选择获取“选项1”选择值1,值2和...计算的values3将由KO自动重新计算。以values1为例,它将调用
self.remaining("option 1");
values2 * values3也将调用剩余但未定义,因为它们尚未被选中。
self.remaining(null);
将值数组过滤为尚未选择且不是当前值的选项。因此,对剩余的第一次调用将导致[ "option 1", "option 2", "option 3"]
。对剩余的第二次和第三次调用将导致[ "option 2", "option 3"]
。
如果取消选择第一个选择,则执行相同的操作并返回所有选项。
希望这有帮助。
答案 1 :(得分:0)
当我必须做类似的事情时,我在项目上有一个IsSet
属性,以及两个计算的observable,一个用于设置它的值,另一个用于未设置的值:
var ViewModel = function(data) {
this.self = this;
self.originalList = ko.observableArray(data.list);
self.selectedItems = ko.computed(function() {
return ko.utils.arrayFilter(function(item) { return item.IsSet(); });
});
self.unselectedItems = ko.computed(function() {
return ko.utils.arrayFilter(function(item) { return !item.IsSet(); });
});
};