Using a modal instead of confirm()

I’m trying to replace a confirm() method with a modal with a pair of yes/no buttons. I have got so far but now I’m stuck. I realise that having prevented the default, I can’t now use returnValue = true but I’m not sure what to do. The delete options are extracted from a database using PHP.

Here is my codepen:

Hey @Gandalf, since you have to wait for some click event to fire you might have showbox() return a promise, which would be fulfilled if the user confirms and otherwise be rejected. I suppose the simplest way would be to just use the resolve() / reject() functions as event handlers – these would then be specific to each opened modal and have to be removed afterwards:

const modal = document.getElementById('modalHolder')
const btnYes = modal.querySelector('#btnYes')
const btnNo = modal.querySelector('#btnNo')

function showbox () {
  let yesHandler
  let noHandler

  modal.style.display = 'flex'

  return new Promise((resolve, reject) => {
    yesHandler = resolve
    noHandler = reject

    btnYes.addEventListener('click', yesHandler)
    btnNo.addEventListener('click', noHandler)
  }).finally(() => {
    modal.style.display = 'none'

    btnYes.removeEventListener('click', yesHandler)
    btnNo.removeEventListener('click', noHandler)
  })
}

const del = document.querySelectorAll('.btnDelete')
for (let i = 0; i < del.length; i++) {
  del[i].addEventListener('click', function (e) {
    e.preventDefault()
    showbox().then(() => {
      console.log('Delete stuff')
    }).catch(() => {
      console.log('Do nothing')
    })
  })
}
1 Like

I have approached this differently. A simple method is to save the value of ‘href’ to a global variable when a delete button is clicked. The value of ‘href’ will then be available after clicking ‘Yes’.

An alternative approach is to pass the value of ‘href’ (or at least the value of ‘k’) to the showbox() function so it’s then available after clicking ‘Yes’. I have used this approach in the CodePen below. I have also changed the <a> tags to <button> tags as they are not hyperlinks. The code to perform the required deletion would be inserted where indicated by a JavaScript comment.

2 Likes

Thanks chaps.

I’ll have to look at these later when time permits.

I was wondering how I got the value of k. I thought I might need to use a data value.

:slight_smile:

I’m having a go with both of these solutions.

@m3g4p0p in yours how do I pass the value of k so that at this point

console.log('Delete stuff')

I can add something like

window.location = "delete.php?k=" + k;

?

The modal doesn’t do anything by itself, it just informs the caller whether the user confirmed or not; so you wouldn’t actually need to pass it, you can set the location right in the then() callback… e.g. with links as in your original pen:

for (let i = 0; i < del.length; i++) {
  del[i].addEventListener('click', function (e) {
    e.preventDefault()
    showbox().then(() => {
      // Delete element
      window.location = e.target.href
    }).catch(() => {
      // Do nothing
    })
  })
}

Or with data-k attributes:

window.location = 'delete.php?k=' + e.target.dataset.k
1 Like

Ah, that simple! Cheers, squire.

1 Like

I use the dialog element and open it as a modal dialog.
It has a means of returning a result.
According to can I use it is supported in edge and chrome and can be enabled in firefox and I have just tested it in safari ver. 15 and it seems to work though the default styling is different to chrome styling. It defaults to opening to the centre of the screen.

2 Likes

Thanks @dennisjn I’d not come across the dialog element. According to CanIUse it doesn’t seem to have good support yet, and it ought not to work in Safari 15 :upside_down_face:

Uh nice, I wasn’t aware of method="dialog" forms… FWIW, here’s a pen:

Very nice indeed. :-)

1 Like