0

I want to show a modal for confirm the action when you change the selected value in a b-form-selected. I can't to stop the event and it always changes the value before the modal shows. Is there an option for this?

<b-form-select
    id="serviceType"
    v-model="serviceTypeSelected"
    class="dropdown textfield"
    :data-value="serviceTypeSelected"
    :value="serviceTypeSelected"
    required
    @change="changeServiceType">
    <option
      v-for="option in serviceTypeList"
      :key="option.serviceTypeId"
      :value="option.serviceTypeId">
      {{ option.serviceTypeName }}
    </option>
  </b-form-select>

function changeServiceType () {
     this.$bvModal.msgBoxConfirm('Please confirm that you want to delete everything.', {
          title: 'Please Confirm',
          size: 'sm',
          okTitle: 'YES',
          cancelTitle: 'NO',
          centered: true
        })
          .then(value => {
            if (value) {
              //do things
            } else {
              //nothing
            }
          })
          .catch(err => {
            // An error occurred
          })
}
Izaskun DA
  • 39
  • 2
  • 7

2 Answers2

2

Here's how i would suggest doing it. You have one data property selectedOption which you bind to your b-select, this option will be what is shown in the select.

You then have another data property actualOption which is the final value. So when you change your b-select value, you open the dialog to confirm. If the user confirms, you set actualOption to the new selected value. If the user declines you set this.selectedOption back to the old value, which is the value of actualOption.

window.onload = () => {
  new Vue({
    el: '#app',
    data() {
      return {
        selectedOption: 0,
        actualOption: 0,
        options: [
          { value: 0, label: 'Orange' },
          { value: 1, label: 'Apple' },
          { value: 2, label: 'Banana' },
          { value: 3, label: 'Strawberry' },
          { value: 4, label: 'Mango' }
        ]
      }
    },
    methods: {
      onOptionChanged(value) {
        this.$bvModal.msgBoxConfirm('Please confirm that you want to delete everything.')
        .then(confirmed => {
          if(confirmed) {
            this.actualOption = value;
          } else {
            this.selectedOption = this.actualOption;
          }
        }).
        catch(() => {
          /* Reset the value in case of an error */
          this.selectedOption = this.actualOption;
        })
      }
    }
  })
}
<link href="https://unpkg.com/bootstrap@4.4.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://unpkg.com/bootstrap-vue@2.3.0/dist/bootstrap-vue.css" rel="stylesheet"/>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.3.0/dist/bootstrap-vue.js"></script>

<div id="app">
  <b-select
      v-model="selectedOption"
      required
      @change="onOptionChanged">
      <option
        v-for="option in options"
        :key="option.value"
        :value="option.value">
        {{ option.label }}
      </option>
    </b-select>
</div>
Hiws
  • 8,230
  • 1
  • 19
  • 36
  • I was using this and it works. However, once option is selected - if we want to allow clicking on same option again to re-open the modal (to edit something in my case), it will not open modal unless we change the select option to something else and come back to that. Is there a way to handle it? – rsram312 May 19 '23 at 14:26
-1

I have used Sweet Alerts to replicate your situation, works the same just change it to your model.

Create an additional value in your data object which you are going to use to check against your model input.

In your @change function, you check if user agrees to change data or to cancel the change.

If user cancels : set serviceTypeSelected v-model to the new inputVal value (your history) to undo the change.

If user accepts : run confirmation dialog and set inputVal to the input value (this is to save your history)

data() {
  return {
    serviceTypeSelected: '',
    inputVal: '',
  }
},
methods: {
  changeServiceType(id){
    this.$swal({
        title: "Are you sure ?",
        text: "You are going to change the service type!",
        type: "warning",
        showCancelButton: true,
        confirmButtonColor: "#f2ab59",
        confirmButtonText: "Yes, change service type!",
        cancelButtonText: "No, cancel!",
    }).then((confirmed) => {
        if (confirmed.value) {
            this.$swal(
                'Changed!',
                'Service type has been changed.',
                'success'
            );
            this.inputVal = id;
        } else {
            this.$swal("Cancelled", "Service type hasn't been changed !", "error");
            this.serviceTypeSelected = this.inputVal;
            // this.serviceTypeSelected = '';
            // this.inputVal = '';
        }
    });
}
}
<b-form-select
    id="serviceType"
    v-model="serviceTypeSelected"
    :data-value="serviceTypeSelected"
    :value="serviceTypeSelected"
    class="dropdown textfield"
    required
    @change="changeServiceType">
    <option>Test1</option>
    <option>Test2</option>
</b-form-select>

If interested in Sweet Alerts as I used it for this particular question.

vue-sweetalert2 npm

npm i vue-sweetalert2


Sweet Alert has a nice documentation and is good to use with vue.js.
Tomm
  • 1,021
  • 2
  • 14
  • 34
  • Downvoters could also comment why this is downvoted. – Tomm Jan 29 '20 at 09:43
  • You suggest to implement a completely new component which doesn't solve his current issue. and the actual useful information to his problem is placed at the bottom of your answer. – Hiws Jan 29 '20 at 10:16