Search code examples
javascriptasynchronousasync-awaitconfirmconfirmation

How to get a return value from a custom confirmation box


I'm trying to get a return value from a custom confirmation box base on which button a user clicks. Not sure how to go about it asynchronously.

The template for the confirmation window is premade, and the confirmation_box() assigns text to the specified elements.

If the user clicks yes, I want to return a value of 1/true, which would allow me to proceed with the next step. If no is clicked, the confirmation window will simply close and the code stop there.

async function confirmation_box(msg = 'Are you sure?', false_btn = 'No', true_btn = 'Yes') {

  let confirmation_modal = document.getElementById('overlay');
  let true_el = confirmation_modal.querySelector('.true_btn');
  let false_el = confirmation_modal.querySelector('.false_btn');

  // assign text to elements
  confirmation_modal.querySelector('#confirmation_msg').textContent = msg;
  true_el.textContent = true_btn;
  false_el.textContent = false_btn;

  confirmation_modal.classList.add('show');

  true_el.addEventListener('click', await
    function() {
      confirmation_modal.classList.remove('show');
      return 1;
    });

  false_el.addEventListener('click', await
    function() {
      confirmation_modal.classList.remove('show');
      return 0;
    });
}


async function delete_demo() {
  let result = await confirmation_box('are you sure you want to delete this?');
  console.log(`Confirmation result ${result}`);

  if (result) {
    document.getElementById('demo_text').remove();
  }


}
body {
  height: 100vh;
  display: -ms-grid;
  display: grid;
  place-content: center;
}

#overlay {
  top: 0;
  left: 0;
  opacity: 0;
  width: 100%;
  height: 100%;
  display: -ms-grid;
  display: grid;
  position: fixed;
  visibility: hidden;
  place-content: center;
  background: rgba(0, 0, 0, 0.5);
}

#overlay.show {
  opacity: 1;
  visibility: visible;
}

.modal {
  padding: 10px;
  background: #fff;
  border: 1px solid #000;
}
<body>
  <div class="container">

    <p id='demo_text'>Demo text</p>

    <button onclick='delete_demo()'>Delete Demo</button>


    <div id="overlay">
      <div class="modal">
        <p id="confirmation_msg"></p>

        <div>
          <button class="false_btn"></button>
          <button class="true_btn"></button>
        </div>
      </div>
    </div>
  </div>

</body>


Solution

  • You are nearly there.

    The problem is that the confirmation_box function doesn't return a Promise, so your await confirmation_box statement doesn't do the waiting that you expected it to do. The fixed code has three changes.

    1. confirmation_box returns a Promise with all of the code inside the promise.

    2. return 0 and return 1 were changed to resolve(0) and resolve(1)

    3. As Barmar said, don't use addEventListener inside anything that might loop when you don't want multiple event listeners. I just changed it to an onclick since it uses the resolve function available inside the Promise area.

    Here's the fixed code:

    async function confirmation_box(msg = 'Are you sure?', false_btn = 'No', true_btn = 'Yes') {
        return new Promise(function(resolve){
          let confirmation_modal = document.getElementById('overlay');
          let true_el = confirmation_modal.querySelector('.true_btn');
          let false_el = confirmation_modal.querySelector('.false_btn');
    
          // assign text to elements
          confirmation_modal.querySelector('#confirmation_msg').textContent = msg;
          true_el.textContent = true_btn;
          false_el.textContent = false_btn;
    
          confirmation_modal.classList.add('show');
    
          true_el.onclick = function() {
              confirmation_modal.classList.remove('show');
              resolve(1);
            };
    
          false_el.onclick = function() {
              confirmation_modal.classList.remove('show');
              resolve(0);
            };
        });
    }
    
    
    async function delete_demo() {
      let result = await confirmation_box('are you sure you want to delete this?');
      console.log(`Confirmation result ${result}`);
    
      if (result) {
        document.getElementById('demo_text').remove();
      }
    
    
    }
    body {
      height: 100vh;
      display: -ms-grid;
      display: grid;
      place-content: center;
    }
    
    #overlay {
      top: 0;
      left: 0;
      opacity: 0;
      width: 100%;
      height: 100%;
      display: -ms-grid;
      display: grid;
      position: fixed;
      visibility: hidden;
      place-content: center;
      background: rgba(0, 0, 0, 0.5);
    }
    
    #overlay.show {
      opacity: 1;
      visibility: visible;
    }
    
    .modal {
      padding: 10px;
      background: #fff;
      border: 1px solid #000;
    }
    <body>
      <div class="container">
    
        <p id='demo_text'>Demo text</p>
    
        <button onclick='delete_demo()'>Delete Demo</button>
    
    
        <div id="overlay">
          <div class="modal">
            <p id="confirmation_msg"></p>
    
            <div>
              <button class="false_btn"></button>
              <button class="true_btn"></button>
            </div>
          </div>
        </div>
      </div>
    </body>