JavaScript Form submit() and Events
Learn how the submit event, form.submit() and form.requestSubmit() work in JavaScript: validation, preventDefault(), and the submitter button.
Handling form submissions is one of the most common jobs in front-end JavaScript. Forms are how users send data back to a server — logging in, registering, searching, checking out — so you almost always want a chance to validate, transform, or confirm that data before it leaves the page.
There are two related but distinct tools for this:
- The
submitevent — fired by the browser when the user tries to submit a form (clicking a submit button, pressing Enter in a field). This is where you run validation and decide whether to allow or cancel the send. - The
form.submit()method — submits the form programmatically from your code, without any user action.
A key gotcha that trips up many developers: these two are not symmetric. Calling form.submit() does not fire the submit event and skips constraint validation entirely. We'll cover why, and what to use instead.
Understanding the submit Event
The submit event fires when a form is about to send its data. Crucially, it is cancelable: calling event.preventDefault() inside the handler stops the browser from navigating away, which lets you keep the user on the page to validate input, show errors, or send the data with fetch instead.
The event fires when:
- The user clicks a
<button type="submit">or<input type="submit">inside the form. - The user presses Enter while focused in a text field of a form that has a submit button.
It does not fire when you call form.submit() from JavaScript (see below).
Example: Form Validation Before Submission
This script prevents the form from being submitted if the fields are not filled correctly, providing an error message to the user. It relies on the browser's built-in constraint validation (the required attribute and type="email") via checkValidity().
<div>
<form style="display: flex; justify-content: center; gap: 2px; align-items: center; flex-direction: column;" id="registrationForm">
Username: <input type="text" name="username" required />
Email: <input type="email" name="email" required />
<button type="submit">Register</button>
</form>
<div id="message" style="margin-top: 10px; text-align:center;"></div> <!-- Message container for feedback -->
<script>
const form = document.getElementById('registrationForm');
form.addEventListener('submit', function(event) {
event.preventDefault(); // Prevent actual form submission to a server
const messageDiv = document.getElementById('message');
if (!this.checkValidity()) {
messageDiv.textContent = 'Please fill all required fields correctly.';
messageDiv.style.color = 'red'; // Display the message in red for errors
} else {
messageDiv.textContent = 'The form was successfully submitted.';
messageDiv.style.color = 'green'; // Display the message in green for success
form.reset(); // Reset the form fields after successful submission
}
});
</script>
</div>JavaScript Functionality:
- Event Listener: An event listener is attached to the form that triggers when the form is attempted to be submitted.
- Validation Check: The
checkValidity()function is used here. It's a built-in HTML form method that checks all inputs in the form against their validation rules (like therequiredattribute in this case). If any field does not meet its validation rule, the function returns false. - Prevent Submission: If
checkValidity()returns false (meaning the form has invalid or empty required fields), the script prevents the form from being submitted to a server. Instead, it displays a message asking the user to fill in all required fields correctly. - Handling Submission: If all fields are valid, the form displays a success message instead of showing an empty page or submitting to a server. In a real app, this is where you'd call
fetch()to send the data.
Reading the submitted data
Inside the handler you usually want the values the user typed. The cleanest way is the FormData object, which collects every named control in one step:
const form = document.getElementById("registrationForm");
form.addEventListener("submit", (event) => {
event.preventDefault();
const data = Object.fromEntries(new FormData(form));
console.log(data.username, data.email);
// data is a plain object: { username: "...", email: "..." }
});Knowing which button was clicked
When a form has several submit buttons (for example "Save" vs. "Delete"), the submit event tells you which one triggered it via event.submitter:
form.addEventListener("submit", (event) => {
event.preventDefault();
// event.submitter is the button element that caused submission
console.log("Submitted via:", event.submitter?.value);
});Leveraging the .submit() Method
The .submit() method initiates form submission programmatically — straight from your code, with no user click required. It is useful when a form must be sent after some condition is met (a timer, a passed automated check, a value computed in JavaScript).
Two caveats make .submit() behave differently from a user-driven submit:
- It does not fire the
submitevent, so any validation or logic you attached to that event is skipped. - It does not run the browser's constraint validation, so
requiredandtyperules are ignored.
This is by design — historically .submit() was meant to send without re-running the very handler that called it (which would otherwise loop). Most of the time you should prefer form.requestSubmit() instead (covered below), which behaves like a real user submit.
Example: Programmatic Form Submission
The example below submits a form from code as soon as the page loads. Because the form has no action attribute, it posts back to the current page; the alert shows the hidden field's value so you can see what would be sent:
<!DOCTYPE html>
<html>
<head>
<title>Auto Submit Form Demo</title>
</head>
<body>
<form id="autoSubmitForm">
<input type="hidden" name="data" value="Automatic Submission" />
</form>
<script>
function submitFormAutomatically() {
document.getElementById('autoSubmitForm').submit();
alert("Form submitted with data: " + document.getElementById('autoSubmitForm').data.value);
}
document.addEventListener('DOMContentLoaded', submitFormAutomatically); // Call the function when the DOM is ready
</script>
</body>
</html>Note that document.getElementById('autoSubmitForm').data works because named form controls are exposed as properties on the form element — form.data returns the <input name="data"> element, and .value reads its value.
Prefer requestSubmit() over submit()
form.requestSubmit() is the modern, safer counterpart to form.submit(). Unlike .submit(), it:
- fires the
submitevent, so your validation handlers run; - runs the browser's constraint validation and shows native error bubbles if a field is invalid;
- optionally accepts a button so
event.submitteris set, e.g.form.requestSubmit(saveButton).
const form = document.getElementById("registrationForm");
// Behaves exactly like a real user click on the submit button:
form.requestSubmit();If you truly need the bypass behavior of .submit() but still want your handler to run, you can dispatch the event yourself with form.dispatchEvent(new Event('submit', { cancelable: true })) — but in almost all cases requestSubmit() is the right call.
Combining .submit() with Event Listeners
You can also gate submission behind your own conditions: only send the form when some criteria are met. The example below uses a plain (non-submit) button so nothing happens until the JavaScript decides to call submit().
Example: Conditional Form Submission
<form id="conditionalForm">
Accept Terms: <input type="checkbox" id="acceptTerms">
<button type="button" onclick="checkAndSubmit()">Submit</button>
</form>
<script>
function checkAndSubmit() {
var form = document.getElementById('conditionalForm');
var termsCheckbox = document.getElementById('acceptTerms');
if (termsCheckbox.checked) {
form.submit();
} else {
alert('You must accept the terms and conditions to proceed.');
}
}
</script>This code provides a button that, when clicked, checks if a checkbox is marked before submitting the form. If the terms are not accepted, it alerts the user. Note that because form.submit() is used here, the submit event will not fire — swap it for form.requestSubmit() if you also have a submit listener you want to run.
submit event vs. submit() vs. requestSubmit()
| Behavior | submit event | form.submit() | form.requestSubmit() |
|---|---|---|---|
| Triggered by user action | Yes | No (code only) | No (code only) |
Fires the submit event | — | No | Yes |
| Runs constraint validation | n/a | No | Yes |
Can be cancelled (preventDefault) | Yes | No | Yes (via the event) |
Sets event.submitter | Yes | No | Yes (pass a button) |
Rule of thumb: listen to the submit event to validate and intercept; call requestSubmit() to trigger a submission from code; reach for .submit() only when you specifically need to bypass your own handlers.
Conclusion
The submit event lets you intercept and validate a form before it leaves the page, while .submit() and requestSubmit() let you send it from code. The most important takeaway is that .submit() silently skips both the submit event and validation — so prefer requestSubmit() unless you deliberately want that bypass. Combined with event.preventDefault() and FormData, these tools give you full control over how user input is collected and sent.
To go further, see form properties and methods, the constraint validation API, the change and input events for live field reactions, and focus and blur for field-level interaction.