0

Here is my code below:

<a
  @click="destroy"
  :class="['button', { 'is-loading': deleting }]"
>
  Delete
</a>

data: () => ({
  deleting: false
}),
destroy () {
  this.deleting = true

  if (!confirm('Sure?') {
    this.deleting = false
    return
  }
}

As a result a modal dialog displays and this.deleting is not true :/

Is it possible to change deleting property before dialog?

b00sted 'snail'
  • 354
  • 1
  • 13
  • 27
  • can you make a [mcve]? – mplungjan Aug 29 '18 at 08:12
  • What do you mean with `this.deleting is not true`. At the time `confirm` is called and the modal is show `this.deleting` is true. But if you expect that the vue component does some different rendering cause you changed `this.deleting` then no this won't happen, because `confirm` is blocking. – t.niese Aug 29 '18 at 08:14

2 Answers2

1

It seems like the UI hasn't updated by the time the confirmation dialog appears. You could delay the confirmation dialog a bit using setTimeout(func, 0) to ensure that the UI has updated.

It should be something similar to:

destroy () {
  this.deleting = true

  // Store reference to `this` for access during callback.
  var self = this;

  setTimeout(function() {
      if (!confirm('Sure?') {
        // self - refers to `this` in the outer context.
        self.deleting = false
        return
      }
  }, 0);
}

OR

destroy () {
  this.deleting = true

  setTimeout(() => {
      if (!confirm('Sure?') {
        this.deleting = false
        return
      }
  }, 0);
}

requestAnimationFrame might also be a good alternative.

See: How to tell when a dynamically created element has rendered

Note: I haven't tested this, because you don't have an MCVE in the question.

Nisarg Shah
  • 14,151
  • 6
  • 34
  • 55
1

At the time confirm is called and the modal is show this.deleting is true. But if you expect that the vue component does some different rendering cause you changed this.deleting then no this won't happen, because confirm is blocking.

I would suggest to wrap the native dialog handling for confirm, alert, prompt into own function. That not only allows them to be opend/tiggered async, but also gives the possibility to replace them by custom dialog boxes later.

With await/async and Promises there is a nice way to do this:

you dialog module

const dlgs = {}

dlgs.confirm = function (message) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(confirm(message))
    },0)
  })
}

your vue component

<a
  @click="destroy"
  :class="['button', { 'is-loading': deleting }]"
>
  Delete
</a>


data: () => ({
  deleting: false
}),
async destroy () {
  this.deleting = true

  if (! await dlgs.confirm('Sure?') {
    this.deleting = false
    return
  }

  // do the deleting
}

Having custom dialog boxes that are implemented using html, have the advantage that you can update informations in background while the dialog box is opened.

t.niese
  • 39,256
  • 9
  • 74
  • 101