首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何防止select表单在Vue中对话框完成之前被更改

如何防止select表单在Vue中对话框完成之前被更改
EN

Stack Overflow用户
提问于 2019-04-16 04:44:29
回答 2查看 3.2K关注 0票数 4

我有一个带有各种选项的选择字段。当用户单击该字段以更改当前选择时,我需要启动一个提示,让用户确认他们希望继续更改,因为这将需要他们重做一个很长的过程。如果他们取消了更改,则需要防止所选选项发生更改,因为即使是一个快速的临时更改也会触发客户端上的自动保存。因此,other solutions似乎不起作用,因为它们保存原始值,让更改通过,然后在必要时恢复更改。

我不确定这是否是“正确的”方法,但我决定创建一个函数,该函数将在每次单击选择字段时运行。我在下面的代码中使用本机confirm方法成功地解决了这个问题。我相信它是有效的,因为confirm的同步特性允许我在任何事件侦听器收到更改之前恢复它,所以基本上就像没有发生过更改一样(如果我错了,请纠正我)。不幸的是,由于兼容性的原因,我不能使用confirm

代码语言:javascript
复制
// This works, but I need to be able to do it without using 'confirm'
handlePotentialOptionChange(e){
  if (this.currentOption !== e.target.value){
    if (!confirm(`Are you sure you want to change the option from ${this.currentOption} to ${e.target.value}? You will be required to redo multiple fields.`)){
      this.selectModel = this.currentOption // If user cancels the change, revert it to the original option. 
    }
  }
}

因为我不能使用confirm,所以我使用dialog component from Buefy。但是,它是异步运行的,这意味着当用户尝试选择不同的选项时,选项更改将在他们回答对话框之前完成。如果取消,下面的代码将恢复更改,但到那时已经太晚了,没有任何用处。

代码语言:javascript
复制
handlePotentialOptionChange(e){
  if (this.currentOption !== e.target.value){
    this.$dialog.confirm({
      message: `Are you sure you want to change the option from ${this.currentOption} to ${e.target.value}? You will be required to redo multiple fields.`,
      onConfirm: () => this.selectModel = e.target.value,
      onCancel: () => this.selectModel = this.currentOption
    })
  }
}

是否可以让用户看到选项下拉列表,但禁用任何类型的选项更改,直到提示得到响应,以便我可以在async onConfirmonCancel函数中相应地更改选项?或者我应该使用某种完全不同的方法?谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-04-16 09:08:26

我将创建一个组合了选择元素和确认对话框的新组件,并让它发出一个'input‘事件(仅当新的选择被确认时),并接收一个'value’prop,这样父级就可以在v-model中使用它。

运行代码片段并通读下面的示例。

代码语言:javascript
复制
Vue.component('select-confirm', {
  props: ['value'],

  data: function () {
    return {
      showConfirmationDialog: false,
      unconfirmedValue: 'a'
    }
  },

  methods: {
    cancelSelection () {
      this.showConfirmationDialog = false
    },
    
    confirmSelection () {
      this.$emit('input', this.unconfirmedValue)
      this.showConfirmationDialog = false
    },
    
    showConfirmation (e) {
      this.unconfirmedValue = e.currentTarget.value
      this.showConfirmationDialog = true
    }
  },

  template: `
    <div class="select-confirm">
      <select :value="value" @change="showConfirmation">
        <option value="a">A</option>
        <option value="b">B</option>
      </select>
      <div v-if="showConfirmationDialog" class="confirmation-dialog">
        <p>Are you sure you want to change your selection to '{{ this.unconfirmedValue }}'?</p>
        <button @click="confirmSelection">Yes</button>
        <button @click="cancelSelection">No</button>
      </div>
    </div>
  `
})

new Vue({
  el: '#app',
  data () {
    return {
      confirmedValue: 'a'
    }
  }
})
代码语言:javascript
复制
<script src="https://unpkg.com/vue@2.6.8/dist/vue.min.js"></script>
<div id="app">
  <select-confirm v-model="confirmedValue"></select-confirm>
  <p>Confirmed value is '{{ confirmedValue }}'.</p>
</div>

票数 6
EN

Stack Overflow用户

发布于 2021-09-04 13:23:58

我想提出一个使用$refs和单向v-bind的解决方案。

代码语言:javascript
复制
<template>
    <div>
        <select ref="mySelect" v-bind:value="storedChoice" @input="vOn">
            <option
                v-for="option in selectOptions"
                :value="option.value"
                :key="option.value"
            >
                {{ option.name }}
            </option>
        </select>
    </div>
</template>
<script>
export default {
    data() {
        return {
            selectOptions: [
                { value: 1, name: "Choice 1" },
                { value: 2, name: "Choice 2" },
                { value: 3, name: "Choice 3" },
            ],
            storedChoice: 3,
        };
    },
    methods: {
        vOn(event) {
            const newValue = event.target.value;
            const indexPriorToChange = this.selectOptions.findIndex(
                (el) => el.value === this.storedChoice
            );
            this.$refs.mySelect.options.selectedIndex = indexPriorToChange; // this resets the index to the one resulting from value
            let confirmDialog = new Promise((resolve) => {
                // this promise is a mockup for an asycnc dialog returning true / false
                setTimeout(() => {
                    resolve(true); // resolve true or false
                }, 1500);
            });
            confirmDialog.then((res) => {
                if (res) {
                    this.storedChoice = newValue;
                } else console.log("No changes");
            });
        },
    },
};
</script>

其思想是将v-modelv-bind实例与select字段一起使用,以阻止存储数据的自动更改。同时,我们使用v-on监听输入事件,当它发生时,我们立即访问select字段,并将它的索引(由于用户的操作已经被浏览器更改)设置为当前“真实”数据产生的索引。然后我们启动异步验证,如果验证是肯定的,我们将更改存储的数据,选择字段将自动更新(如果不是,我们可以手动设置索引,但它在没有它的情况下适用于我,只需使用Vue的反应性)。

这个操作可能会触发关于直接操作DOM的Vue warning (尽管出于某种原因,上面的代码没有为我做这件事),但是我认为这是一个合理的用法,因为我们不是试图显示覆盖我们的数据模型的数据-相反,我们正在阻止浏览器显示尚未存储在模型中的数据。

您可以看到对BootstrapVue的选择组件使用getter/setter方法的here我的替代解决方案。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55696976

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档