Skip to content
beginner

Handle Form Submissions with JavaScript

You fill out a form, hit submit, and the whole page jumps. Everything you typed is gone. The browser did what forms do by default: it sent the data and…

Published 2026-09-06Updated 2026-09-129 min read
A sleek and contemporary library interior, showcasing modern architectural design and ample natural lighting.
A sleek and contemporary library interior, showcasing modern architectural design and ample natural lighting. Photo by Marcus Lenk on Pexels.

You fill out a form, hit submit, and the whole page jumps. Everything you typed is gone. The browser did what forms do by default: it sent the data and loaded a fresh page.

But here's the thing: you can step in before that happens. The JavaScript form submit event is your moment to take control. Instead of letting the browser reload, you can read what the user typed, check it, and show feedback right on the page.

That's what we'll build together in this tutorial.

Why Your Form Reloads (and How to Stop It)

When you submit an HTML form, the browser's default behavior is to send the form data to a server and then navigate or reload the page. That's how forms have worked since the early web—the page goes away, and something new comes back.

Modern web apps often don't want that. They want to stay on the same page, check the input, and only send data if everything looks right.

That's where the submit event comes in. When a user tries to submit a form, the browser fires a submit event on the form element before it does its default reload. If your JavaScript is listening, you can intercept that moment, run your own code, and decide what happens next.

You already know how to select elements and attach event listeners from earlier tutorials. Now we'll put those skills together for a real-world task: handling a form submission without losing the page.

Here's our goal: build a small form where JavaScript reads what the user typed, checks that it's not empty, and shows a message on the page—all without a single reload.

Set Up a Simple Form to Test

Let's start with a minimal HTML form. We'll keep it to one text input so you can focus on the submit mechanism, not on form complexity.

Create a file called form-demo.html and add this:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Form Demo</title>
</head>
<body>
  <form id="signup-form">
    <label for="username">Username:</label>
    <input type="text" id="username" name="username">
    <button type="submit">Sign Up</button>
  </form>

  <p id="message"></p>

  <script>
    // Your JavaScript goes here
  </script>
</body>
</html>

A few things to notice:

  • The <form> has an id="signup-form" so JavaScript can find it.
  • The text input has an id="username" so we can read its value later.
  • The <p id="message"> is empty for now. That's where we'll show our result.
  • The <script> tag is at the bottom of the body, after the form elements.

If you open this file in a browser and click "Sign Up," the page will reload instantly. Nothing seems to happen because there's no server to send data to—but the reload still occurs. Let's fix that.

Listen for the Submit Event

To handle the submit event, we attach an event listener to the form element, not the button. This is a common beginner mistake, so let's be clear about why.

There are two ways a user can submit a form:

  1. Clicking the submit button.
  2. Pressing Enter while typing in a text field.

Both actions fire the same submit event on the form. If you attach your listener to the button, you'll catch the click but miss the Enter key. Attach it to the form, and you catch both.

Add this to your <script> tag:

const form = document.querySelector('#signup-form');

form.addEventListener('submit', function(event) {
  console.log('Form submitted!');
});

Save the file and open it in your browser. Open the developer console (right-click → Inspect → Console tab), then try both ways of submitting: click the button, and press Enter in the text field.

You should see "Form submitted!" in the console both times.

That's your JavaScript form submit event working. But you'll also notice the page still reloads. Let's stop that next.

Knowledge check

Check your understanding

Answer this question before you continue.

Where should you attach the `submit` event listener to catch both a button click and pressing Enter in the input?
Single Choice

Focus: Identify which element should receive a listener for all form submissions, including Enter-key submissions.

Stop the Page Reload with preventDefault()

Flowchart showing a form submit event entering the JavaScript handler, where preventDefault() stops the browser reload, then the code reads the username and checks whether it is empty. The flow ends with either an error message or a welcome message; a separate path without preventDefault() ends in a page reload.
The submit handler stops the default reload first, then reads, validates, and reports the form value.

Here's the problem: our event handler runs, but the browser's default behavior still happens afterward. The page reloads, and any message we try to show gets wiped out instantly.

This is the single most common reason beginner form code "doesn't work." The code runs fine—but the reload erases the result before you can see it.

The fix is a method called preventDefault(). When the browser fires the submit event, it passes an event object to your handler. That object carries details about what happened, and it also has a way to cancel the default behavior.

Update your handler:

const form = document.querySelector('#signup-form');

form.addEventListener('submit', function(event) {
  event.preventDefault();
  console.log('Form submitted!');
});

Now try submitting again. The console message still appears, but the page stays perfectly still. No reload. No jump.

That's preventDefault() in action: it cancels the browser's default form submission so your code can take over. In practice, you'll use this whenever you want to validate input or send data with JavaScript instead of letting the browser handle it.

Knowledge check

Check your understanding

Answer this question before you continue.

Why does the example call `event.preventDefault()` inside the submit handler?
Misconception Check

Focus: Explain how `event.preventDefault()` changes the browser's default form behavior.

Read What the User Typed

Now that the page stays put, we can actually do something useful. Let's read the text the user typed into the input field.

Every input element has a .value property that holds its current text. We select the input the same way we selected the form, then read .value:

const form = document.querySelector('#signup-form');
const usernameInput = document.querySelector('#username');

form.addEventListener('submit', function(event) {
  event.preventDefault();
  
  const username = usernameInput.value;
  console.log(username);
});

Type something in the field and submit. You'll see exactly what you typed appear in the console.

One important detail: .value always returns a string, even if the input looks like a number. If you had an input type="number" and the user typed 42, .value would give you the string "42", not the number 42. For our text input, that's fine—we just want to check whether the user typed anything at all.

Knowledge check

Check your understanding

Answer this question before you continue.

If the user types `42` into the text input, what does `console.log(username)` print in the article's code?
Output Prediction

Focus: Predict the type and value read from a text input with its `.value` property.

const username = usernameInput.value;
console.log(username);

Validate a Simple Value

Reading the input is only half the job. The real reason to intercept form submission is to validate what the user typed before accepting it.

Let's add a simple rule: the username must not be empty. If it is, we'll show an error. If it's not, we'll show a success message.

const form = document.querySelector('#signup-form');
const usernameInput = document.querySelector('#username');

form.addEventListener('submit', function(event) {
  event.preventDefault();
  
  const username = usernameInput.value;
  
  if (username === '') {
    console.log('Error: username is required');
  } else {
    console.log('Success: welcome, ' + username + '!');
  }
});

This is the basic pattern behind the validation you see on real signup and contact forms:

  1. Read the input.
  2. Check it against a rule.
  3. Branch: show an error or accept the value.

Try submitting with an empty field, then with text. Watch the console in both cases.

The if/else structure is simple, but it's the same logic that powers much more complex validation. Once you understand this flow, you can extend it to check email formats, password lengths, or anything else.

Knowledge check

Check your understanding

Answer this question before you continue.

Which condition correctly implements the article's rule that an empty username should show an error?
Debugging

Focus: Choose the validation condition that distinguishes an empty username from a nonempty username.

const username = usernameInput.value;

if (/* condition */) {
  console.log('Error: username is required');
} else {
  console.log('Success: welcome, ' + username + '!');
}

Show the Result on the Page

Console messages are great for testing, but your users will never see them. Let's display the result right on the page using that empty <p> element.

We'll use textContent to set the message. This is safer and simpler than innerHTML because it treats the content as plain text, not HTML. If a user typed <b>hello</b>, textContent would show it literally instead of rendering it as bold text.

Here's the complete working example:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Form Demo</title>
</head>
<body>
  <form id="signup-form">
    <label for="username">Username:</label>
    <input type="text" id="username" name="username">
    <button type="submit">Sign Up</button>
  </form>

  <p id="message"></p>

  <script>
    const form = document.querySelector('#signup-form');
    const usernameInput = document.querySelector('#username');
    const message = document.querySelector('#message');

    form.addEventListener('submit', function(event) {
      event.preventDefault();
      
      const username = usernameInput.value;
      
      if (username === '') {
        message.textContent = 'Error: username is required.';
      } else {
        message.textContent = 'Welcome, ' + username + '!';
      }
    });
  </script>
</body>
</html>

Save, refresh, and test both cases:

Case 1: Empty input

Click "Sign Up" without typing anything. The page stays still, and you'll see:

Error: username is required.

Case 2: Valid input

Type alex and submit. You'll see:

Welcome, alex!

No reload. No lost input. The page simply updates with feedback. That's the power of handling form submissions with JavaScript.

Common Beginner Mistakes to Avoid

If your form isn't behaving, check these three mistakes first. They account for nearly every beginner issue I've seen.

Mistake 1: Forgetting preventDefault()

Symptom: Your message flashes on screen for a split second, then disappears. Or you never see it at all.

Cause: The page reloads right after your handler runs, wiping out any changes you made.

Fix: Call event.preventDefault() as the first line inside your submit handler.

Mistake 2: Attaching the listener to the button

Symptom: Clicking the button works, but pressing Enter in the text field doesn't trigger your code.

Cause: The submit event fires on the form, not the button. A click listener on the button misses Enter-key submissions entirely.

Fix: Attach your listener to the form element:

form.addEventListener('submit', function(event) { ... });

Mistake 3: Running the script before the form exists

Symptom: You get an error like Cannot read properties of null and nothing works.

Cause: Your JavaScript runs before the browser has parsed the form HTML, so querySelector can't find the elements.

Fix: Place your <script> tag at the end of the <body>, after your form markup. That's why our example puts the script last.

Practice: Build Your Own Check

Now it's your turn to extend what we've built. Here are three challenges, in order of difficulty:

Challenge 1: Change the validation rule so the username must be at least 3 characters long. Hint: check username.length instead of comparing to an empty string.

Challenge 2: Add a second input field for an email address. Read both values on submit and show them both in the message.

Challenge 3: Temporarily remove event.preventDefault() and submit the form. Watch what happens to your message. Then add it back. This experiment will make the reload problem unforgettable.

When you're ready to go further, the natural next step is sending your validated data to a server. That's where real signup forms start to come alive—but you've already mastered the hardest part: taking control at the submit event and keeping the page in your hands instead of the browser's.

Knowledge check

Final check

Finish the article by checking the ideas you just learned.

With the completed example, what appears in the page when the user types `alex` and submits?
Question 1 of 2Output Prediction

Focus: Predict the visible message produced for a valid username.

A script gets `null` from `document.querySelector('#signup-form')`, causing a null-property error. According to the article, what is the appropriate fix?
Question 2 of 2Debugging

Focus: Diagnose why a form query returns null when the script runs before the form markup is parsed.

const form = document.querySelector('#signup-form');
form.addEventListener('submit', handleSubmit);

References

  1. Sending forms through JavaScript - Learn web development | MDNdeveloper.mozilla.org
8sources checked
8source domains
5searches run

Research updated Sep 6, 2026

Keep learning

Related tutorials

Continue with nearby JavaScript topics and beginner-friendly explanations.

A breathtaking view of a tropical sunset with vibrant colors reflecting on the calm sea.
beginner
7 min read

Arrow Functions Basics

JavaScript arrow functions let you write the same functions you already know in fewer lines. The idea isn't new—only the syntax is shorter.

Read tutorial