skip to Main Content

I have a form for which I want to use a dialog to confirm submission. It would be convenient for me to nest the dialog inside the form so that it is easier to dertermine which dialog belongs to which form when querySelector’ing them with javascript. Below are two minimal examples of this. In the first the dialog is outside the form and works as expected. In the second the dialog is nested inside the form and for some reason only the Yes button works, the No button does nothing.

const form = document.getElementById("myForm");
const dialog = document.getElementById("confirmDialog");
const confirmBtn = document.getElementById("confirmBtn");
const cancelBtn = document.getElementById("cancelBtn");

form.addEventListener("submit", function(event) {
  event.preventDefault();
  dialog.showModal();
});

confirmBtn.addEventListener("click", function() {
  dialog.close();
  form.submit(); // Continue form submission
});

cancelBtn.addEventListener("click", function() {
  dialog.close(); // Cancel form submission
});
<form id="myForm">
  <input type="submit" value="Submit" />
</form>
<dialog id="confirmDialog">
  <p>Are you sure you want to submit this form?</p>
  <menu>
    <button id="confirmBtn">Yes</button>
    <button id="cancelBtn">No</button>
  </menu>
</dialog>
const form = document.getElementById("myForm");
const dialog = document.getElementById("confirmDialog");
const confirmBtn = document.getElementById("confirmBtn");
const cancelBtn = document.getElementById("cancelBtn");

form.addEventListener("submit", function(event) {
  event.preventDefault();
  dialog.showModal();
});

confirmBtn.addEventListener("click", function() {
  dialog.close();
  form.submit(); // Continue form submission
});

cancelBtn.addEventListener("click", function() {
  dialog.close(); // Cancel form submission
});
<form id="myForm">
  <input type="submit" value="Submit" />
  <dialog id="confirmDialog">
    <p>Are you sure you want to submit this form?</p>
    <menu>
      <button id="confirmBtn">Yes</button>
      <button id="cancelBtn">No</button>
    </menu>
  </dialog>
</form>

2

Answers


  1. It would seem when the dialog is nested inside the form, the click event on the "No" button triggers the form submission by default, preventing you from handling the cancel action at your discretion.

    You can modify the code to prevent the default form submission when the "No" button is clicked by calling the preventDefault() method:

    const form = document.getElementById("myForm");
    const dialog = document.getElementById("confirmDialog");
    const confirmBtn = document.getElementById("confirmBtn");
    const cancelBtn = document.getElementById("cancelBtn");
    
    form.addEventListener("submit", function(event) {
      event.preventDefault();
      dialog.showModal();
    });
    
    confirmBtn.addEventListener("click", function() {
      dialog.close();
      form.submit(); // Continue form submission
    });
    
    cancelBtn.addEventListener("click", function() {
      event.preventDefault(); // Cancel form submission
      dialog.close(); // Cancel form submission
    
    });
    <form id="myForm">
      <input type="submit" value="Submit" />
      <dialog id="confirmDialog">
        <p>Are you sure you want to submit this form?</p>
        <menu>
          <button id="confirmBtn">Yes</button>
          <button id="cancelBtn">No</button>
        </menu>
      </dialog>
    </form>
    Login or Signup to reply.
  2. Any button inside a <form> will be a submit button by default.

    submit: The button submits the form data to the server. This is the default if the attribute is not specified for buttons associated with a <form>, or if the attribute is an empty or invalid value.

    So you could avoid the default action, which is submitting the form, by using the preventDefault() method in your listener.

    I would recommend changing the type of these buttons, to solve the issue closer to the root cause and avoid unforeseen consequences. Assistive technology, for example, might otherwise assume they are submit buttons.

    button: The button has no default behavior, and does nothing when pressed by default. It can have client-side scripts listen to the element’s events, which are triggered when the events occur.

    const form = document.getElementById("myForm");
    const dialog = document.getElementById("confirmDialog");
    const confirmBtn = document.getElementById("confirmBtn");
    const cancelBtn = document.getElementById("cancelBtn");
    
    form.addEventListener("submit", function(event) {
      event.preventDefault();
      dialog.showModal();
    });
    
    confirmBtn.addEventListener("click", function() {
      dialog.close();
      form.submit(); // Continue form submission
    });
    
    cancelBtn.addEventListener("click", function() {
      dialog.close(); // Cancel form submission
    });
    <form id="myForm">
      <input type="submit" value="Submit" />
      <dialog id="confirmDialog">
        <p>Are you sure you want to submit this form?</p>
        <menu>
          <button type="button" id="confirmBtn">Yes</button>
          <button type="button" id="cancelBtn">No</button>
        </menu>
      </dialog>
    </form>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search