多个下拉列表,没有重复的值

  • 本文关键字:下拉列表 vue.js vuejs2
  • 更新时间 :
  • 英文 :


我试图复制一个Vue组件,这是一个项目列表,每个项目包含一个下拉菜单和一个删除按钮。会有一个"按钮,将新项添加到列表中,如下面的代码片段所示。

要求是当用户选择一个选项时,该选项将不可用于(或删除)任何其他项。换句话说,所选的选项值不应该重复。这与这个问题中的想法非常相似(jQuery防止多个下拉框中的重复选择)

当用户重新选择或删除一个项目时,附加在该项目上的已选择选项应再次添加到"available"列表。因此,选项列表是"反应性的"。和动态的。

例如,对于第一项,如果我选择"Option 1"选项1"当"添加新项目"时,不应该出现在选项列表中。点击。如果第一项被删除,选项1"将可再次选择,等等,…

这就是我到目前为止得到的,其想法是option将存储所有选项数据,selectedValueArray将负责存储每个项目的选定选项值,selectableOptions数组将等于options集减去selectedValueArray。通过与item (change option, remove)交互,selectedValueArrayselectableOptions数组也会相应改变。

我可以用JavaScript做到这一点。然而,我是Vue的新手,不知道如何在Vue中有效地做到这一点。我创建的代码片段的问题是,由于可用选项来自selectableOptions数组,所以当从selectableOptions中删除一个项目时,它也会影响所选选项。(例如:If "Option 1",则第一项中的下拉列表将为空白,因为"选项1"已从可选列表中删除)。如有任何帮助,不胜感激。

var app = new Vue({
el: "#app",
data: {
options: [],
items: [],
selectableOptions: [],
selectedValueArray: [],
},
mounted() {
this.options = [
{
name: "Option 1",
value: 1,
},
{
name: "Option 2",
value: 2,
},
{
name: "Option 3",
value: 3,
},
{
name: "Option 4",
value: 4,
},
{
name: "Option 5",
value: 5,
},
{
name: "Option 6",
value: 6,
}
];
this.selectableOptions = this.options;
},
methods: {
addItem: function () {
this.items.push({
'value': 0
});
},
removeItem: function (index) {
this.$delete(this.items, index);

},
changeOption: function () {
this.selectedValueArray = [];
for (let i = 0; i < this.items.length; i++) {
let selectedValue = this.items[i].value;
this.selectedValueArray.push(selectedValue);
}

this.selectableOptions = this.options.filter(                   
option => { 
return this.selectedValueArray.indexOf(option.value) == -1;
})                 
},
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(item, index) in items">
<select 
v-model="item.value">
<option v-for="(option) in selectableOptions" :value="option.value">{{option.name}}</option>
</select>
<button @click="removeItem(index)">Remove this item</button>
</div>
<button @click="addItem">Add new item</button>
</div>

如果您想简单地禁用一个值存在于items对象数组中的选项(您正在使用v-model指令绑定,因此它反映了一个"live";用户选择的选项集),然后使用一个方法返回一个禁用状态:

<option v-for="(option) in options" :value="option.value" v-bind:disabled="isDisabled(option)">{{option.name}}</option>

然后,您可以定义一个isDisabled(option)方法,该方法返回一个布尔值来指示给定的option的值是否已经存在于您的数组中:

isDisabled: function(option) {
return this.items.map(item => item.value).includes(option.value);
}

参见下面的示例证明:

var app = new Vue({
el: "#app",
data: {
options: [],
items: [],
selectedValueArray: [],
},
mounted() {
this.options = [{
name: "Option 1",
value: 1,
},
{
name: "Option 2",
value: 2,
},
{
name: "Option 3",
value: 3,
},
{
name: "Option 4",
value: 4,
},
{
name: "Option 5",
value: 5,
},
{
name: "Option 6",
value: 6,
}
];
},
methods: {
addItem: function() {
this.items.push({
'value': 0
});
},
removeItem: function(index) {
this.$delete(this.items, index);
},

isDisabled: function(option) {
return this.items.map(item => item.value).includes(option.value);
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(item, index) in items">
<select v-model="item.value">
<option v-for="(option) in options" :value="option.value" v-bind:disabled="isDisabled(option)">{{option.name}}</option>
</select>
<button @click="removeItem(index)">Remove this item</button>
</div>
<button @click="addItem">Add new item</button>
</div>

你必须使用computed属性来过滤selectableOptions

像这样的

{
computed: {
computedSelectable() {
const chosenValues = this.selectedValueArray.map((i) => i.value);
return this.selectableOptions.filter((item) =>
!chosenValues.includes(item.value)
);
},
}
}

改进的答案,选择disabled选项的<select>元素将不会提交。用v-show代替

var app = new Vue({
el: "#app",
data: {
options: [],
items: [],
selectedValueArray: [],
},
mounted() {
this.options = [{
name: "Option 1",
value: 1,
},
{
name: "Option 2",
value: 2,
},
{
name: "Option 3",
value: 3,
},
{
name: "Option 4",
value: 4,
},
{
name: "Option 5",
value: 5,
},
{
name: "Option 6",
value: 6,
}
];
},
methods: {
addItem: function() {
this.items.push({
'value': 0
});
},
removeItem: function(index) {
this.$delete(this.items, index);
},

isShown: function(option) {
return !(this.items.map(item => item.value).includes(option.value));
},
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(item, index) in items">
<select v-model="item.value">
<option v-for="(option) in options" :value="option.value" v-show="isShown(option)">{{option.name}}</option>
</select>
<button @click="removeItem(index)">Remove this item</button>
</div>
<button @click="addItem" v-show="items.length<options.length">Add new item</button>
</div>

最新更新