在 vue 应用程序中添加新值时从下拉列表中删除值

问题描述 投票:0回答:1

我正在尝试在我的 vue 项目中创建日期过滤器。所以对于这一点,观点是:

<div class="dropdown-item d-flex flex-column">
                                    <div
                                        v-for="(filter, index) in dateFilters"
                                        :key="index"
                                        class="dropdown-item-inner"
                                    >
                                        <div class="mb-2 d-flex">
                                            <select v-model="filter.dateType" class="form-select mr-1">
                                                <option value="startDate">Start Date</option>
                                                <option value="endDate">End Date</option>
                                            </select>
                                            <select v-model="filter.filterType" class="form-select mr-1">
                                                <option
                                                    v-for="option in dateOptions"
                                                    :value="option.value"
                                                    :key="option.value"
                                                >
                                                    {{ option.label }}
                                                </option>
                                            </select>
                                            <input type="date" v-model="filter.date" class="form-control" />
                                            <button
                                                :disabled="dateFilters.length < 2"
                                                class="button is-transparent m-0 d-flex horizontal-center vertical-center"
                                                @click="clearDateFilterRule(index)"
                                            >
                                                <i class="fas fa-trash mr-2"></i>
                                            </button>
                                        </div>
                                    </div>
                                    <div class="date-filter-buttons">
                                        <button
                                            v-if="dateFilters.length < 8"
                                            class="button is-transparent m-0 d-flex horizontal-center vertical-center"
                                            @click="addDateFilter"
                                        >
                                            <i class="fas fa-plus mr-2"></i>Add Rule
                                        </button>
                                        <button
                                            type="button"
                                            class="button is-transparent m-0"
                                            @click="clearDateFilters"
                                        >
                                            Clear
                                        </button>
                                    </div>
                                </div>

实际查看如下:

所以我有 dateOptions 和 dateFilters:

data() {
        return {
            dateFilters: [
                {
                    dateType: "startDate",
                    filterType: "eq",
                    date: "",
                },
            ],
            dateOptions: [
                {value: "eq", label: "Date is"},
                {value: "not", label: "Date is not"},
                {value: "lte", label: "Date is before"},
                {value: "gte", label: "Date is after"},
            ],
        };
    },

这是我的添加事件:

addDateFilter() {
            const selectedValue = this.dateFilters.map((filter) => filter.filterType);

            this.dateOptions = this.dateOptions.filter(option => !selectedValue.includes(option.value));

            if (this.dateOptions.length > 0) {
                this.dateFilters.push({
                    dateType: "startDate",
                    filterType: this.dateOptions[0].value,
                    date: "",
                });
            }
        },

所以我的目标是当我单击添加规则按钮(即 addDateFilter 事件)时,我将您在图片中看到的同一行添加到 dateFilters 中。但我想从中删除 dateOptions 下拉菜单(日期是)。例如,如果在第一行中使用日期并在中间下拉列表的下一行中推送日期过滤器,则应删除日期。这一部分,我是成功的。但问题是,当我将行推入 dateFilters 时,第一行的值也消失了。所以我有这样的看法:

如何解决?

vue.js vuejs2 vuejs3 vue-component
1个回答
0
投票

您的

addDateFilter
的问题在于它没有反应性。当下拉列表更改时,其他下拉列表需要对这些更改做出反应,即在一个下拉列表中选择不同的选项应该使原始选项在所有下拉列表中可用。

我将首先集中精力解释它,假设“开始日期”作为唯一可用的日期类型,因为这就是我首先解决的方法(或者如果您只想跳到考虑“开始日期”的最终解决方案和“结束日期”,向下滚动)。

仅限“开始日期”

使用计算属性,我们可以反应性地跟踪下拉列表中所有当前选定和未选定的日期选项。

computed: {
  // getter for all selected options
  selectedOptions() {
    return this.dateFilters.map(df => df.filterType)
  },
  // getter for all unselected options
  unselectedOptions() {
    return this.dateOptions.filter(o => !this.selectedOptions.includes(o.value))
  }
},

addDateFilter
方法可以简化为仅将新过滤器推送到 dateFilters 数组

addDateFilter() {
  this.dateFilters.push({
    dateType: 'startDate',
    filterType: this.unselectedOptions[0].value,
    date: ''
  })
},

每个下拉列表应列出所有未选择的选项+当前选择的选项。我将在一个新方法中返回此有效选项列表,该方法将所选选项作为参数。然后可以在

v-for
中使用此方法来返回每个下拉列表的所有有效选项。

// return unused options with currently selected option
validDateOptions(val) {
  const selected = this.dateOptions.find(o => o.value === val)
  return [ ...this.unselectedOptions, selected]
},
<select v-model="filter.filterType" class="form-select mr-1">
  <option
    v-for="option in validDateOptions(filter.filterType)"
    :key="option.value"
    :value="option.value"
  >
    {{ option.label }}
  </option>
</select>

Vue SFC Playground 示例


允许“开始日期”和“结束日期”

由于“开始日期”和“结束日期”都可以具有相同的选定选项之一,因此我们必须在上述方法中添加

dateType
作为附加过滤器和参数。唯一的问题是我们应该避免使用
computed
属性的参数,因此这些实际上需要更改为方法:

methods: {
  // getter for all selected options
  selectedOptions(type) {
    return this.dateFilters.filter(df => df.dateType === type).map(df => df.filterType)
  },
  // getter for all unselected options
  unselectedOptions(type) {
    return this.dateOptions.filter(o => !this.selectedOptions(type).includes(o.value))
  },

addDateFilter
默认情况下会添加一个新的“startDate”过滤器,但如果已添加所有这些过滤器,则需要添加一个“endDate”过滤器。

addDateFilter() {
  let type = 'startDate'
  if (this.unselectedOptions(type).length === 0) {
    type = 'endDate'
  }
  this.dateFilters.push({
    dateType: type,
    filterType: this.unselectedOptions(type)[0].value,
    date: ''
  })
},

新的

validDateOptions
现在还需要一个额外的参数:

// return unused options with currently selected option
validDateOptions(type, val) {
  const selected = this.dateOptions.find(o => o.value === val)
  return [ ...this.unselectedOptions(type), selected]
},

模板代码中提供:

<select v-model="filter.filterType" class="form-select mr-1">
  <option
    v-for="option in validDateOptions(filter.dateType, filter.filterType)"
    :key="option.value"
    :value="option.value"
  >
    {{ option.label }}
  </option>
</select>

Vue Playground 示例

未解决的问题

上面的代码没有考虑如果有两个具有相同选项但不同类型的下拉菜单并且您将它们更改为相同类型会发生什么,例如

开始日期 |日期是 |月/日/年

结束日期 |日期是 |月/日/年

更改为:

开始日期 |日期是 |月/日/年

开始日期 |日期是 |月/日/年

这将是无效的,但尚不清楚应如何处理。您需要使用一个方法向 dateType 下拉列表添加一个事件侦听器,该方法可以决定是否忽略更改、显示错误、交换日期类型值或执行其他操作。由于这不是您最初问题的一部分,并且有多种方法可以处理它,因此我将其留给您。

© www.soinside.com 2019 - 2024. All rights reserved.