mrwooster
mrwooster

Reputation: 24207

Intercept a form submit in JavaScript and prevent normal submission

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

Upvotes: 112

Views: 210596

Answers (5)

mplungjan
mplungjan

Reputation: 177796

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>

Upvotes: 44

kba
kba

Reputation: 19466

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

Upvotes: 22

Vitaliy Borisok
Vitaliy Borisok

Reputation: 861

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);

Upvotes: 5

Michael McTiernan
Michael McTiernan

Reputation: 5313

<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()

Upvotes: 121

user657496
user657496

Reputation:

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

$('button').click(function() {
    preventDefault();
    captureForm();
});

Upvotes: 1

Related Questions