110

There seems to be lots of info on how to submit a form using javascript, but I am looking for a solution to capture when a form has been submitted and intercept it in javascript.

HTML

<form>
 <input type="text" name="in" value="some data" />
 <button type="submit">Go</button>
</form>

When a user presses the submit button, I do not want the form to be submitted, but instead I would like a JavaScript function to be called.

function captureForm() {
 // do some stuff with the values in the form
 // stop form from being submitted
}

A quick hack would be to add an onclick function to the button but I do not like this solution... there are many ways to submit a form... e.g. pressing return while on an input, which this does not account for.

Ty

1

5 Answers 5

118
<form id="my-form">
    <input type="text" name="in" value="some data" />
    <button type="submit">Go</button>
</form>

In JS:

function processForm(e) {
    if (e.preventDefault) e.preventDefault();

    /* do what you want with the form */

    // You must return false to prevent the default form behavior
    return false;
}

var form = document.getElementById('my-form');
if (form.attachEvent) {
    form.attachEvent("submit", processForm);
} else {
    form.addEventListener("submit", processForm);
}

Edit: in my opinion, this approach is better than setting the onSubmit attribute on the form since it maintains separation of mark-up and functionality. But that's just my two cents.

Edit2: Updated my example to include preventDefault()

9
  • this does not work with chrome either as far as i can see using jsbin.com/ejoyas Commented Feb 10, 2013 at 17:19
  • 2
    Note that the attach event code needs to be executed AFTER the form is available in the dom. For example using window.onload=function() { ... } to wrap it
    – mplungjan
    Commented Feb 26, 2013 at 6:17
  • when does the processform() function gets called sir?
    – user1899563
    Commented Sep 16, 2013 at 11:24
  • Not sure because I don't use IE, but I think the attachEvent parameter should be "onsubmit". Commented Jun 10, 2015 at 19:18
  • 1
    in 2017, check for addEventListener before falling back to attachEvent since IE9+ supports addEventListener.
    – cowbert
    Commented Jan 6, 2018 at 4:38
44

You cannot attach events before the elements you attach them to has loaded

It is recommended to use eventListeners - here one when the page loads and another when the form is submitted.

NOTE: NEVER call anything in a form "submit"

This works since IE9:

Plain/Vanilla JS

// Should only be triggered on first page load
console.log('ho');

window.addEventListener("DOMContentLoaded", function() {
  document.getElementById('my-form').addEventListener("submit", function(e) {
    e.preventDefault(); // before the code
    /* do what you want with the form */

    // Will be triggered on form submit
    console.log('hi');
  })
});
<form id="my-form">
  <input type="text" name="in" value="some data" />
  <button type="submit">Go</button>
</form>

jQuery

// Should only be triggered on first page load
console.log('ho');

$(function() {
  $('#my-form').on("submit", function(e) {
    e.preventDefault(); // cancel the actual submit

    /* do what you want with the form */

    // Will be triggered on form submit
    console.log('hi');
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<form id="my-form">
  <input type="text" name="in" value="some data" />
  <button type="submit">Go</button>
</form>

Not recommended but will work

If you do not need more than one event handler, you can use onload and onsubmit

// Should only be triggered on first page load
console.log('ho');

window.onload = function() {
  document.getElementById('my-form').onsubmit = function() {
    /* do what you want with the form */

    // Should be triggered on form submit
    console.log('hi');
    // You must return false to prevent the default form behavior
    return false;
  }
}
<form id="my-form">
  <input type="text" name="in" value="some data" />
  <button type="submit">Go</button>
</form>

4
  • I think you mean: $('#my-form).on('submit', function() { alert('hi'); });
    – Michiel
    Commented Nov 25, 2013 at 13:44
  • 1
    @Michiel while what you provide is what you use with jQuery, this solution provided is a pure JS solution with no dependency on jQuery. The solution here would similar to using <form onsubmit="alert('hi'); return false;"> Commented Jul 14, 2016 at 15:16
  • 2
    @ChrisMarisic - a few years old :) I have updated the answer anyway to include jQuery
    – mplungjan
    Commented Jul 14, 2016 at 16:28
  • Thank you so much :)
    – thedude12
    Commented Nov 18, 2021 at 16:59
22

<form onSubmit="return captureForm()"> that should do. Make sure that your captureForm() method returns false.

8
  • Follow up: Is there a way to capture a form submit with JavaScript without affecting the browser's handling of the required attribute?
    – Elisabeth
    Commented Nov 20, 2011 at 23:18
  • @Elisabeth What handling of what attribute? If you mean to not prevent the form from actually being submitted, you just need captureForm() to return true instead of false.
    – kba
    Commented Nov 20, 2011 at 23:30
  • The browser's handling of the "required" attribute. I do want to prevent the form from being submitted. But by returning false instead of true (or using preventDefault()), it changes how the browser handles the "required" attribute on an input element. Try it for yourself: add <code>required</code> to an input element, capture the submit and see if you lose the default behavior for it.
    – Elisabeth
    Commented Nov 21, 2011 at 0:43
  • I don't seem to lose default behaviour. It works fine in Chrome. You'll need to come up with an erroneous example in order for me to help.
    – kba
    Commented Nov 21, 2011 at 1:08
  • 1
    Ok, here's the form: <form method="get" action=""> <label for="color">What is your favorite color?</label> <input type="text" name="color" placeholder="blue" required> <input id="submit" type="submit" value="Submit"> </form> and here's the code: function processForm(e) { var form = document.querySelector("form"); for (var i = 0; i < form.childNodes.length; i++) { var node = form.childNodes[i]; /* do stuff with nodes / } / return false; */ } Testing in opera. Uncomment the last line, required fails. (Sorry code doesn't work well in comments)
    – Elisabeth
    Commented Nov 21, 2011 at 5:38
5

Another option to handle all requests I used in my practice for cases when onload can't help is to handle javascript submit, html submit, ajax requests. These code should be added in the top of body element to create listener before any form rendered and submitted.

In example I set hidden field to any form on page on its submission even if it happens before page load.

//Handles jquery, dojo, etc. ajax requests
(function (send) {
    var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");
    XMLHttpRequest.prototype.send = function (data) {
        if (isNotEmptyString(token) && isNotEmptyString(header)) {
            this.setRequestHeader(header, token);
        }
        send.call(this, data);
    };
})(XMLHttpRequest.prototype.send);


//Handles javascript submit
(function (submit) {
    HTMLFormElement.prototype.submit = function (data) {
        var token = $("meta[name='_csrf']").attr("content");
        var paramName = $("meta[name='_csrf_parameterName']").attr("content");
        $('<input>').attr({
            type: 'hidden',
            name: paramName,
            value: token
        }).appendTo(this);

        submit.call(this, data);
    };
})(HTMLFormElement.prototype.submit);


//Handles html submit
document.body.addEventListener('submit', function (event) {
    var token = $("meta[name='_csrf']").attr("content");
    var paramName = $("meta[name='_csrf_parameterName']").attr("content");
    $('<input>').attr({
        type: 'hidden',
        name: paramName,
        value: token
    }).appendTo(event.target);
}, false);
1

Use @Kristian Antonsen's answer, or you can use:

$('button').click(function() {
    preventDefault();
    captureForm();
});
3
  • 7
    for anyone else doing this 2.5 years (or more) later, you need to pass the click event as a parameter to the function (as in function(e) and call e.preventDefault() Commented Nov 5, 2013 at 5:10
  • Can also be captured on the "submit" event for the form, if your input[type="submit"] is used, and that puts you in the form context versus the context of the button. The callback will always have the context of the event, so you do not necessarily have to pass 'e' as an argument, you simply refer to 'event'.
    – augurone
    Commented Aug 10, 2015 at 18:34
  • 2
    This is not recommended, as submission can be triggered be a keypress.
    – jhpratt
    Commented Dec 1, 2017 at 6:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.