Javascript 淘汰JS:从其他相同下拉列表中删除选定值

Javascript 淘汰JS:从其他相同下拉列表中删除选定值,javascript,drop-down-menu,knockout.js,Javascript,Drop Down Menu,Knockout.js,我正在研究一个问答模型,我有多个下拉列表,其中包含相同的数据(答案库,如果你愿意的话)。这里的业务逻辑是,一旦有人选择了一个问题的答案,该答案只能使用一次,而不能用于其他问题 因此,我找到了一种方法,可以将所有下拉列表绑定到包含答案的单个observableArray,以便所有下拉列表都包含相同的选项。我想做的是订阅一个下拉列表的当前值(多个下拉列表中的一个),并从与之相关的所有其他下拉列表中删除所选值。使用Knockout,我已经能够订阅一个回调函数,以适应视图中不断变化的值 在我的回调函数中

我正在研究一个问答模型,我有多个下拉列表,其中包含相同的数据(答案库,如果你愿意的话)。这里的业务逻辑是,一旦有人选择了一个问题的答案,该答案只能使用一次,而不能用于其他问题

因此,我找到了一种方法,可以将所有下拉列表绑定到包含答案的单个observableArray,以便所有下拉列表都包含相同的选项。我想做的是订阅一个下拉列表的当前值(多个下拉列表中的一个),并从与之相关的所有其他下拉列表中删除所选值。使用Knockout,我已经能够订阅一个回调函数,以适应视图中不断变化的值

在我的回调函数中,我发现使用ObservalArray的
remove
方法从ObservalArray中删除答案是可行的,但不幸的是,它从所有下拉列表中删除了当前选择的答案-包括所选答案!我试着用push命令把它放回去,但这也会导致问题。我似乎无法以我想要的方式隔离更新


以前有没有人用Knockout实现过类似的东西?任何帮助或建议都将不胜感激。

因为您被绑定到一系列选项,如果您从其中删除一个项目,那么选项绑定将正确反映这一点。您可以为要绑定到的每个选择框使用Computed创建独立的虚拟列表

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());

编辑

下面是上面的工作原理。您需要将每个选择绑定到它自己的可观察对象,以便在第一个选择值时可以更新其他值。如果您只是绑定到同一个列表,并在每次选择一个值时将其删除,那么您也将删除刚才选择的值,KO将相应地更新select元素,它将被完全破坏

上面的代码通过依次过滤每一个来解决这个问题。我将每一个下拉列表重定向到它自己的计算可观察值。这些计算出的观测值只需调用一个过滤函数,该函数在值数组上循环,过滤掉所有已选择的而不是当前选择的值

因此,如果我们从所有未选择的开始,第一次选择得到“选项1”,选择值1,计算出的值2和值3将由KO自动重新计算。以值1为例,它将调用

self.remaining("option 1");
values2*values3还将调用剩余但未定义的,因为它们尚未被选择

self.remaining(null);
“值”数组将过滤为尚未选择且不是当前值的选项。因此,第一次调用remaining将导致
[“选项1”、“选项2”、“选项3”]
。第二次和第三次调用剩余的将导致
[“选项2”,“选项3”]

如果取消选择第一个选项,将执行相同的操作,并返回所有选项


希望这能有所帮助。

因为您绑定到一个选项数组,如果您从其中删除了一个项目,那么选项绑定将正确反映这一点。您可以为要绑定到的每个选择框使用Computed创建独立的虚拟列表

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());

编辑

下面是上面的工作原理。您需要将每个选择绑定到它自己的可观察对象,以便在第一个选择值时可以更新其他值。如果您只是绑定到同一个列表,并在每次选择一个值时将其删除,那么您也将删除刚才选择的值,KO将相应地更新select元素,它将被完全破坏

上面的代码通过依次过滤每一个来解决这个问题。我将每一个下拉列表重定向到它自己的计算可观察值。这些计算出的观测值只需调用一个过滤函数,该函数在值数组上循环,过滤掉所有已选择的而不是当前选择的值

因此,如果我们从所有未选择的开始,第一次选择得到“选项1”,选择值1,计算出的值2和值3将由KO自动重新计算。以值1为例,它将调用

self.remaining("option 1");
values2*values3还将调用剩余但未定义的,因为它们尚未被选择

self.remaining(null);
“值”数组将过滤为尚未选择且不是当前值的选项。因此,第一次调用remaining将导致
[“选项1”、“选项2”、“选项3”]
。第二次和第三次调用剩余的将导致
[“选项2”,“选项3”]

如果取消选择第一个选项,将执行相同的操作,并返回所有选项


希望这能有所帮助。

当我不得不做类似的事情时,我在项目上有一个
IsSet
属性,还有两个计算的可观察值,一个用于设置的值,另一个用于未设置的值:

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(); });
    });
};

当我不得不做类似的事情时,我在项目上有一个
IsSet
属性,以及两个计算的可观察值,一个用于设置它的值,另一个用于未设置它的值:

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(); });
    });
};

这看起来很有希望!谢谢你的回复。我将不得不对它进行大量的按摩,以使它适合我的框架,但我认为这是一个很好的起点。谢谢大家!@午餐317-是的,可能不太合身,但你明白了。您需要为每个下拉列表设置一个单独的过滤器,如何进行剩余的计算取决于您自己。我只是把它们放在数组中,这样我就可以懒洋洋地做indexOf了。我不想问,但我一直在破解这个代码,试图让它在我正在使用的框架内工作。你介意解释一下你的代码吗?也就是说,this.remaining函数,以及在this.selected中观察对象是如何工作的?哇,谢谢你的编辑!我没有意识到,观测值与选择值是绑定在一起的,这让我有点困惑。我想我完全明白你现在做了什么,这太棒了!不幸的是(o