0

I am using rails form_with as a remote form. Before submission I want to display a custom confirm box with a dynamic message. After the box is indeed confirmed I want to eventually submit the form. I came up with 'ajax:beforeSend' event handler :

const form = document.getElementById('assign_sessions_to_employees')
form.addEventListener(
  'ajax:beforeSend',
  (event) => {
    event.preventDefault();
    swal.fire({
      title: 'Are you sure ?',
      text: `You are about to spend ${expectedExpenditure()} credits.`,
      showCancelButton: true,
    }).then((result) => {
      if (result.isConfirmed) {
        console.log('submitting')
        Rails.fire(form, 'submit');
      }
    })
  }
)

This works fine, however when I run Rails.fire(form, 'submit');, when I eventually want to submit the form this retriggers 'ajax:beforeSend' and I get stuck in the loop.

What would be the correct way to achieve this behavior with form_with and rails ujs ?

2
  • Make the event handler a named function instead of an arrow function. That way you can remove the handler. Another technique is to just set a data attribute or add a class to the form element when the user confirms and put a guard statement at the top of the function which returns if it's present. medium.com/beginners-guide-to-mobile-web-development/… Commented Oct 11, 2021 at 9:29
  • @max Could you provide an example ? If I remove the listener in this case then I will no longer be able to show the confirm if a later form submit arises... Commented Oct 11, 2021 at 13:38

1 Answer 1

0

If you use a function declaration (aka a named function) you can remove the event handler with EventTarget.removeEventListener():

function handleConfirmation(event){
  let form = event.target;
  event.preventDefault();
  swal.fire({
     title: 'Are you sure ?',
     text: `You are about to spend ${expectedExpenditure()} credits.`,
     showCancelButton: true,
  }).then((result) => {
     if (result.isConfirmed) {
       console.log('submitting');
       form.removeEventListener('ajax:beforeSend', handleConfirmation);
       Rails.fire(form, 'submit');
     }
    })
  }
}
const form = document.getElementById('assign_sessions_to_employees')
form.addEventListener('ajax:beforeSend', handleConfirmation);

Another alternative is to just set a data attribute in your event handler:

const form = document.getElementById('assign_sessions_to_employees')
form.addEventListener(
  'ajax:beforeSend',
  (event) => {
    if (event.target.dataset.confirmed) { return };
    event.preventDefault();
    swal.fire({
      title: 'Are you sure ?',
      text: `You are about to spend ${expectedExpenditure()} credits.`,
      showCancelButton: true,
    }).then((result) => {
      if (result.isConfirmed) {
        console.log('submitting');
        form.dataset.confirmed = true;
        Rails.fire(form, 'submit');
      }
    })
  }
)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.