admin管理员组文章数量:1356884
I have a select field with various options. When the user clicks the field to change the current selection, I need to launch a prompt to have the user confirm that they wish to continue with the change, since that will require them to redo a long process. If they cancel the change, it needs to prevent the selected option from ever changing as even a quick temporary change will trigger an autosave on the client. Because of this, it seems that other solutions don't work as they save the original value, let the change go through, and then revert the change if necessary.
I'm not sure if this is the "proper" approach, but I decided to create a function that will run each time the select field is clicked. I successfully solved this issue by using the native confirm
method in the following code. I believe it works because confirm
's synchronous nature allows me to revert the change before it is ever received by any event listeners, so it's basically like the change never happened(please correct me if I'm wrong). Unfortunately, I am not allowed to use confirm
due to patibility reasons.
// 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.
}
}
}
Since I cannot use confirm
, I'm using a dialog ponent from Buefy. However, it runs asynchronously which means that when the user attempts to select a different option, the option change will go through before they even answer the dialog. The code below will revert the change if canceled, but by that point it is too late to be of any use.
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
})
}
}
Is it possible to let the user see the option dropdown, but disable any kind of option changes until the prompt is answered, so that I can change the option accordingly inside the async onConfirm
and onCancel
functions? Or should I be using some sort of entirely different approach? Thank you.
I have a select field with various options. When the user clicks the field to change the current selection, I need to launch a prompt to have the user confirm that they wish to continue with the change, since that will require them to redo a long process. If they cancel the change, it needs to prevent the selected option from ever changing as even a quick temporary change will trigger an autosave on the client. Because of this, it seems that other solutions don't work as they save the original value, let the change go through, and then revert the change if necessary.
I'm not sure if this is the "proper" approach, but I decided to create a function that will run each time the select field is clicked. I successfully solved this issue by using the native confirm
method in the following code. I believe it works because confirm
's synchronous nature allows me to revert the change before it is ever received by any event listeners, so it's basically like the change never happened(please correct me if I'm wrong). Unfortunately, I am not allowed to use confirm
due to patibility reasons.
// 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.
}
}
}
Since I cannot use confirm
, I'm using a dialog ponent from Buefy. However, it runs asynchronously which means that when the user attempts to select a different option, the option change will go through before they even answer the dialog. The code below will revert the change if canceled, but by that point it is too late to be of any use.
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
})
}
}
Is it possible to let the user see the option dropdown, but disable any kind of option changes until the prompt is answered, so that I can change the option accordingly inside the async onConfirm
and onCancel
functions? Or should I be using some sort of entirely different approach? Thank you.
2 Answers
Reset to default 7I would create a new ponent that bines the select element and the confirmation dialog and have it emit an 'input' event (only when the new selection has been confirmed) and receive a 'value' prop so the parent can use it with v-model.
Run the code snippet and read through the example below.
Vue.ponent('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'
}
}
})
<script src="https://unpkg./[email protected]/dist/vue.min.js"></script>
<div id="app">
<select-confirm v-model="confirmedValue"></select-confirm>
<p>Confirmed value is '{{ confirmedValue }}'.</p>
</div>
I'd like to propose a solution using $refs and one directional v-bind.
<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>
The idea is to use v-bind
insted of v-model
with the select
field in order to block automatic change of stored data. At the same time we listen with the v-on
to an input event and when it happens we immediatelly access the select field and set it's index (already changed by the browser as result of user's action) to the index resulting from the current 'real' data. Then we launch an async validation and if the validation is positive, we change the stored data and the select field updates itself (if not we might set the index manually, but it worked for me without it, just using the Vue's reactivity).
This operation might trigger Vue warning
about direct manipulation of the DOM (for some reason the above code did not do it for me though), however I think this is a justified use, because we are not trying to display data overriding our data model - on the contrary - we are preventing the browser from displaying data that are not yet stored in the model.
You can see here my alternative solution using getter
/setter
approach for BootstrapVue's select ponent.
版权声明:本文标题:javascript - How to prevent a select form from being changed until dialog completion in Vue - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744048026a2581896.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论