What is the best way to pause execution until a modal window has been closed, and then proceed based on whether the user clicked OK or

Procedure:

  1. I identify the variances between two arrays of objects, such as new additions, deletions, or changes. These variations are recorded in data[1-5]
  2. Based on #1, I generate a text summary (textual representations of objects) for a modal window to inform the user about the identified differences. This summary is saved in someDataToShowInModal.
  3. Once the differences are detected, the modal displaying the summary must be presented to the user. The user has the option to either approve (by clicking OK) or reject (by clicking CANCEL) the modifications.
  4. INQUIRY: How can I wait for the user to click either the OK or CANCEL button on the modal?

    The following code provides two potential solutions, but their implementation process remains unclear:

    1. Encase the modal within a Promise.

    2. Utilize state.doSave and find a way to delay until it is altered by myModalComponent.

  5. Implement the changes when the user selects OK.

Below is pseudo-code illustrating the logic I am trying to enact:

state.js

modalTextSummary = {}

action.js

async myAction ({ state }) {
  let modalClosed
  let someDataToShowInModal = {}

  let data1 = []
  let data2 = []
  let data3 = []
  let data4 = []
  let data5 = []

  // #1. Record variances in "data[1-5]"
  data1.push(xyz1)
  data2.push(xyz2)
  data3.push(xyz3)
  data4.push(xyz4)
  data5.push(xyz5)

  // #2. Create "someDataToShowInModal" based on data[1-5]
  someDataToShowInModal = {xyz}

  // #3. Update "state.modalTextSummary" to trigger
  // the Modal display ("myModalCompont" watches for "modalTextSummary")
  state.modalTextSummary = someDataToShowInModal

  // #4. HOW TO WAIT UNTIL USER CLICKS Modal's "OK" or "CANCEL"?

  // Version 1:
  // something like...
  modalClosed = await myModalComponent

  // Version 2:
  // I could set "state.doSave = ''", which can then be 
  // modified to either 'OK' or 'CANCEL' by "myModalComponent", but how
  // do I monitor state changes in this scenario?
  modalClosed = await state.doSave !== ''

  // #5. Apply modifications
  if (modalCloses === 'OK') {
    // ... code implementing changes based on data from data[1-5]
  }
}

myModalComponent.js

<script>
import { mapState } from 'vuex'

export default {
  computed: {
    ...mapState([
      'modalTextSummary'
    ])
  },

  watch: {
    modalTextSummary: function () {
      if (this.modalTextSummary !== {}) {
        // Bootstrap-vue modal display initiated here
      }
    }
  }
}
</script>

I am familiar with calling a function upon closing a modal using an OK button, but in this situation, temporarily storing data[1-5] in vuex to retrieve them later within the invoked function seems rather complex, thus I am seeking a more straightforward method.

Answer №1

How about considering a refactor for your code? :)

1) It's not ideal for Store actions to be aware of the interface, as it can lead to server-side rendering issues and other complications - not a good practice.

2) One suggestion is to store modal data in the parent component of the modal. Here's a simple example you can refer to: https://jsfiddle.net/yyx990803/70yyx8z2/

By doing this, you can implement something similar to the following (pseudo code):

<my-modal
    v-if="showModal"
    @cancel="processModalCancel"
    @submit="processModalSubmit"
    >
    <!-- Manipulate modalData here -->
</my-modal>

---

openModal() {
    this.showModal = true;
    this.modalData = store.dispatch('prepareDataToShowInModal'); // myAction, first part
},
processModalCancel() {
    this.showModal = false;
    this.modalData = null;
},
processModalSubmit() {
    this.showModal = false;
    store.dispatch('saveModalData', this.modalData); // myAction, second part
    this.modalData = null;
},

Answer №2

Discovered a new approach to implementing this using v2 after coming across a helpful post.

gleam's solution is more concise and cleaner, so it's recommended to go with his method. The following solution I provide is purely for educational purposes.

state.js

modalTextSummary = {}
doSave = false

action.js

// My 'store' file is located at the root. If yours is elsewhere, adjust accordingly :)
import store from '@/store'

async myAction ({ state }) {
  state.doSave = false

  let modalClosed
  let someDataToShowInModal = {}

  let data1 = []
  let data2 = []
  let data3 = []
  let data4 = []
  let data5 = []

  // #1. Add elements to "data[1-5]"
  data1.push(xyz1)
  data2.push(xyz2)
  data3.push(xyz3)
  data4.push(xyz4)
  data5.push(xyz5)

  // #2. Prepare "someDataToShowInModal" based on data[1-5]
  someDataToShowInModal = {xyz}

  // #3. Update "state.modalTextSummary" to trigger opening of Modal (due to "myModalCompont" watching "modalTextSummary")
  state.modalTextSummary = someDataToShowInModal

  // #4. Wait until user closes modal or clicks OK
  const unwatch = store.watch(
    (state) => state.doSave,
    (value) => {

      // #5. Implement changes
      if (value === true) {
        unwatch()
        // ... code to process data from data[1-5]

      } else if (value === 'unwatch') {
        unwatch()
      }
    }
  )
}

Why do we need to unwatch()?

In my scenario, myAction is triggered by a button (named "someButton"), which opens a modal. If the modal is opened and closed multiple times without clicking OK, the watch on state.doSave will also accumulate, potentially leading to unnecessary processing when the OK button is finally clicked. Therefore, we must unwatch state.doSave if the modal is closed without confirming.

myModalComponent.js

<template>
  <b-modal
    ref="myModal"
    ok-title="OK"
    cancel-title="Close"
    @keydown.native.enter="closeModalAndSave"
    @ok="closeModalAndSave"
    @hide="closeModalAndUnwatch"
  >
    {{ modalTextSummary }}
  </b-modal>
</template>

<script>
import { mapState, mapMutations } from 'vuex'

export default {
  computed: {
    ...mapState([
      'modalTextSummary'
    ])
  },

  watch: {
    modalTextSummary: function () {
      if (this.modalTextSummary !== {}) {
        this.$refs.myModal.show()
      }
    }
  },

  methods: {
    ...mapMutations('media', [
      'doSave'
    ]),

    closeModalAndUnwatch (bvEvent) {
      // "this.$refs.myModal.hide()" triggers @hide with "bvEvent.trigger === null".
      // We only need to unwatch if bvEvent.trigger === 'cancel' or 'backdrop',
      // or 'header-close', meaning not null.
      if (bvEvent.trigger !== null) {
        this.doSave('unwatch')
      }
    },

    closeModalAndSave () {
      this.doSave(true)
      this.$refs.myModal.hide()
    }
  } // End of "methods"
}
</script>

Answer №3

If you are utilizing bsModal, it is necessary to have separate function bindings for each button. The modal will remain open until the user clicks either button or clicks outside of the modal. Therefore, make sure to include the rest of the function inside those close or confirm buttons' click events.

<button (click)="confirm()"></button>
<button (click)="Cancel()"></button>
import { BsModalRef} from 'ngx-bootstrap';
constructor(){public modalRef: BsModalRef}

confirm(){
//perform actions 
this.modalRef.close();
}

Cancel(){
//perform actions
this.modalRef.close();
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Come together with Array starting from the specified startIndex and ending at the

I'm curious to know if there is a utility function available that allows for joining arrays while also providing an index. Perhaps Prototype or jQuery already have this feature, but if not, I am willing to create it myself :) What I envision is somet ...

Using clearInterval() within setInterval does not necessarily halt the execution of setInterval

I have set up an ajax GET request to send every 5 seconds using JavaScript setInterval. My goal is to stop the ajax calls when the response status is 'COMPLETED'. I have added a clearInterval within an if condition to achieve this, but unfortunat ...

Tips for adjusting the range slider's increment by selecting a radio button

There are two radio buttons and multiple range sliders available. Each radio button has a distinct value assigned to it. The desired functionality is that when one of the radio buttons is clicked, the maximum value should change (from 12 to 24 or from 24 ...

generate an array composed of promises to be used with Promise.all

Currently, I am working with an array of file paths and my goal is to read all the files inside a Promise.all function, followed by carrying out several tasks. var files = ["./file1.txt", "./file2.txt"] Promise.all(files.forEach(file=>{ /* read file ...

Why does Axios keep timing out despite successful testing in Postman?

Trying to set up a single request for my app using axios with express/node js. Here is the code snippet that was generated through the Postman app. I have attempted different variations by creating my own form, but I always end up with the same result. co ...

What is the proper way to incorporate a standalone Vue library into a Vue application?

I'm currently facing an issue with integrating a vue component library into my vue application. This component library is loaded by a script tag and is set up with webpack using the externals setting to exclude vue dependencies. Therefore, the host bu ...

Capture the contents of a table cell and store it in the clipboard

Is there a way to create a hover copy button in a table cell without actually placing the button inside the <td> tags? The goal is to allow users to easily copy text from a specific column cell by hovering over it. function myFunction() { var c ...

Exploring the method of updating functions in Firebase Admin SDK through spying

Is there a way to monitor the update function in Firebase Admin SDK as shown below? yield admin.database().ref('ref').update(obj) I attempted the following without success: const databaseStub = sinon.stub(); const refStub = sinon.stub(); const ...

Creating a restriction for executing a function only once per user in JavaScript with React

I am working on implementing a like button feature for reviews, where users can like a review but are restricted from liking the same review more than once. const handleHelpfulButtonClick = () => { console.log(review) props.dispatch(incrementi ...

Error in Typescript index: iterating over properties of a typed object

My scenario involves an interface that extends multiple other interfaces from an external library: interface LabeledProps extends TextProps, ComponentProps { id: string; count: number; ... } In a different section of the codebase, there is an ...

Error encountered: Attempting to render an object as a react component is invalid

I am attempting to query data from a Firestore database. My goal is to retrieve all the fields from the Missions collection that have the same ID as the field in Clients/1/Missions. Below, you can find the code for my query: However, when I tried to execu ...

Update the content of an HTML element without having direct access to the HTML code

I am currently in the process of creating a website using a website builder, and I am interested in customizing the default message that is displayed when a required field in the website form is left empty. The form in question is an integral part of the w ...

Obtaining JSON data with Three.js

Is it possible to create a JSON file from a model built with Three.js in Webgl, similar to exporting a JSON model from Blender and loading it with THREE.JSONLoader().load? I would like to know if anyone has experience or information on this. ...

Adjust image size on the client's end

I'm having trouble resizing images that are uploaded through an input field. Currently, I keep encountering this error message: An error occurred while trying to resize the image. The parameter passed to 'readAsArrayBuffer' function is not ...

BackboneJS struggles to redirect to .fail when an API request exceeds the timeout

I'm a newbie to backbone and I've come across some interesting code that adds Deferred to enable the use of promises. Take a look at the snippet below: getPatientInfo: function fetch(options) { var deferred = $.Deferred(); Backbone.Model.p ...

Attaching a listener to a checkbox without relying on the HTML onchange attribute

I need to implement an event listener that will modify some CSS when a specific ID is clicked. However, I want to avoid using HTML onchange for this task. The current code snippet below shows my attempt so far. I suspect there may be an error in how I am ...

The phenomenon of React event bubbling and propagation

I have a simple component structured like this: <div onClick={toggleHidden} className="faq-item-header"> <h3>What is Bookmark?</h3> <img src={iconArrow} alt="arrow" /> </div> https://i.sstatic.net/LdWXs. ...

Which programming language should I utilize to create a webpage that dynamically updates its content from a database?

Seeking advice on a complex task I'm facing. I'm currently managing a vast spreadsheet (266 rows with 70 columns, and growing) which serves as a database. I want to transfer this data from Excel to an intranet page. Currently, I'm using a mi ...

Issue with Datepicker not updating when triggered by event handler

Having an issue with my material-UI datepicker where the date is not updating correctly when I try to select a new one. The initial value set in useState works fine, but I want the datepicker to smoothly update when I choose a different date. You can see a ...

Utilizing a variable string name for a method in Typescript Vue

My objective is to trigger a different function based on the value of a variable. However, when working in VS Code, I receive an error message that states: 'method' implicitly has a type of 'any' because 'type1Func' and &apos ...