Search code examples
javascriptjqueryformsonchangeonsubmit

jQuery multiple forms. Need to catch $(this) forms 'on submit'


I have several forms on a page contain in widget like elements to upload images. There could be one, or there could be 10. Im trying to dynamically, individually catch that particular forms on submit. Here is what I have, but on submit it just refreshes the page. Any ideas how to make this work?

Here is the form:

<form id="med_blog_form_<?=$b['blog_med_id']?>" name="med_blog_form" class="med_blog_form" action="#" method="post">
    <label for="media_blog_file_<?=$b['blog_med_id']?>">
         <div class="btn_sm edit_blog_med_btn">UPLOAD</div>
         <input type="file" id="media_blog_file_<?=$b['blog_med_id']?>" data-blog_med_id="<?=$b['blog_med_id']?>" class="media_blog_file" name="media_upload" hidden/>
         <input type="hidden" name="upload_type" value="blog_media_upload" />
         <input type="hidden" name="blog_id" value="<?=$blog_id?>" />
         <input type="hidden" name="filename" value="<?=$b['src']?>" />
     </label>
</form>

and here is the jQuery:

$(".media_blog_file").change(function() {

    blog_med_id = $(this).data("blog_med_id");

    this_form = $(this).closest("form");
    this_form.submit();

    this_form.on('submit',(function(e) {

        e.preventDefault();

        alert("form submit "+blog_med_id);
        //do other stuff here...

    })
    )

})

Solution

  • There's a couple of issues here...

    1. Don't register event handlers within event handlers. That's rarely / never what you want to do

    2. You really don't need jQuery for this

    Instead, add two delegated event handlers; one to listen for file changes and trigger submit events, and one to listen for form submit events

    document.addEventListener('change', (e) => {
      if (e.target.matches('input[type=file].media_blog_file')) {
        e.target.closest('form')?.requestSubmit();
      }
    });
    
    document.addEventListener('submit', (e) => {
      if (e.target.matches('form.med_blog_form')) {
        e.preventDefault();
        const blog_med_id = e.target.querySelector(
          'input[type=file][data-blog_med_id]',
        )?.dataset.blog_med_id;
    
        // alert(`form submit ${blog_med_id}`);
        console.log('form submit:', blog_med_id);
      }
    });
    <!-- note PHP parts have been replaced with static values -->
    <form id="med_blog_form_1" name="med_blog_form" class="med_blog_form" action="#" method="post">
      <label for="media_blog_file_1">
             <div class="btn_sm edit_blog_med_btn">UPLOAD</div>
             <input type="file" id="media_blog_file_1" data-blog_med_id="1" class="media_blog_file" name="media_upload" hidden/>
             <input type="hidden" name="upload_type" value="blog_media_upload" />
             <input type="hidden" name="blog_id" value="1" />
             <input type="hidden" name="filename" value="my_file" />
         </label>
    </form>


    I'm using the HTMLFormElement: requestSubmit() method instead of just .submit() as the latter (in vanilla JS) bypasses event listeners and directly submits the form.

    jQuery's .submit() (aka .trigger('submit')) behaves much the same as requestSubmit().