Himanshu SharmaSoftware engineer
Let’s talk

jQuery · Lesson 25 of 45

Form events: submit, change, focus and blur

Handle form submission with jQuery, validate fields on change and blur, show clear error messages, and learn the order of focus, blur, focusin and focusout.

13 minEventsUpdated 23 October 2026

By the end of this lessonValidate a form in the browser before it is sent, give clear per-field feedback, and respond to fields gaining and losing focus.

Handling submission

When a user submits a form, the browser sends it to the server and loads a new page. To check the data first, or to send it with Ajax, handle the form's submit event:

html
<form id="signup">
  <label>Email <input id="email" name="email" type="email"></label>
  <button>Sign up</button>
</form>
<p id="msg"></p>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("#signup").on("submit", function (event) {
    event.preventDefault();
    const email = $("#email").val().trim();
    $("#msg").text("Thanks, we will write to " + email);
    console.log("submitted:", $(this).serialize());
  });
</script>
result
submitted: email=asha%40example.com

Always listen on the form, not on the button's click. Pressing Enter in a text field also submits the form, and only the submit event catches both ways. $(this).serialize() turns the form's named fields into a URL-encoded string, ready to send.

Validating before sending

A typical pattern: check each field, show messages next to the ones with problems, and only continue if everything is fine.

html
<style>
  .error input { border-color: crimson; }
  .hint { color: crimson; font-size: .9em; margin: 2px 0 8px; }
</style>
<form id="contact" novalidate>
  <div class="field"><label>Name <input id="name" name="name"></label></div>
  <div class="field"><label>Email <input id="cemail" name="email" type="email"></label></div>
  <button>Send</button>
</form>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  function showError($input, message) {
    const $field = $input.closest(".field").toggleClass("error", Boolean(message));
    $field.find(".hint").remove();
    if (message) $("<p>", { "class": "hint", text: message }).appendTo($field);
  }

  $("#contact").on("submit", function (event) {
    event.preventDefault();
    const name = $("#name").val().trim();
    const email = $("#cemail").val().trim();

    showError($("#name"), name.length < 2 ? "Please enter your full name." : "");
    showError($("#cemail"), /^\S+@\S+\.\S+$/.test(email) ? "" : "Please enter a valid email address.");

    const errors = $(this).find(".field.error").length;
    console.log(errors ? errors + " field(s) need attention" : "form is valid, sending");
    if (errors) $(this).find(".field.error input").first().trigger("focus");
  });
</script>
result
2 field(s) need attention

The messages are added as text next to each field, and focus moves to the first field with a problem so keyboard and screen reader users land where they need to act. novalidate turns off the browser's own pop-up messages so ours are used instead; without it, the browser would check type="email" and required fields itself before our handler runs.

Browser checks are a convenience for honest users. Always validate again on the server, because anyone can send data without using your form.

change

change fires when a value is committed:

  • for a select, as soon as a new option is chosen;
  • for checkboxes and radios, when they are ticked or unticked;
  • for text fields, when the user leaves the field after changing it (not on every key; that is input).
html
<label><input id="gift" type="checkbox"> This is a gift</label>
<div id="gift-note" hidden><label>Gift message <input name="message"></label></div>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("#gift").on("change", function () {
    $("#gift-note").prop("hidden", !this.checked);
    console.log("gift note shown:", this.checked);
  });
</script>
result
gift note shown: true

Showing or hiding extra fields based on a checkbox or select is the classic use of change.

focus and blur

focus fires when an element gains keyboard focus (by clicking or tabbing into it); blur fires when it loses focus. blur is a good moment to check a field, because the user has finished with it:

html
<label>Phone <input id="phone"></label>
<p id="phone-hint"></p>
<label>Other <input id="other"></label>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("#phone")
    .on("focus", function () { $("#phone-hint").text("Use 10 digits, no spaces."); })
    .on("blur", function () {
      const ok = /^\d{10}$/.test($(this).val());
      $("#phone-hint").text(ok ? "" : "That does not look like a 10-digit number.");
      console.log("phone ok:", ok);
    });
  $("#other").on("click", function () { $(this).trigger("focus"); });
</script>
result
phone ok: false

Checking on blur is kinder than checking on every key: the user is not told off halfway through typing.

focusin and focusout

focus and blur do not bubble, so a handler on the form never hears them from its fields. focusin and focusout are the bubbling versions, so one handler on a container works for every field inside:

html
<style> .field.current { background: #fef9c3; } </style>
<form id="f">
  <div class="field"><input id="a" placeholder="First"></div>
  <div class="field"><input id="b" placeholder="Second"></div>
</form>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("#f")
    .on("focusin", "input", function () { $(this).closest(".field").addClass("current"); })
    .on("focusout", "input", function () { $(this).closest(".field").removeClass("current"); });

  $("#a, #b")
    .on("click", function () { $(this).trigger("focus"); })
    .on("focus blur focusin focusout", function (event) { console.log(event.type, this.id); });
</script>
result
focus a
focusin a
blur a
focusout a
focus b
focusin b

The output shows the order when focus moves from the first field to the second: the old field's blur and focusout, then the new field's focus and focusin. jQuery 4 follows this standard order in every browser; jQuery 3 changed it in some cases, which is worth knowing if old code depends on it. (The handler on the form uses delegation, the subject of the next lesson.)

reset

A form's reset event fires when it is reset with a <button type="reset">. Clear your own messages there too, or they stay behind after the fields are emptied.

Common mistakes

  • Handling the button's click instead of the form's submit.
  • Forgetting preventDefault() and letting the page reload.
  • Using change for live updates on text fields; use input.
  • Putting focus or blur handlers on a container; use focusin/focusout.
  • Trusting browser validation alone.

Exercise

Make a form with a password field and a confirm field. On submit, if they differ, show a message and do not continue; if they match, log passwords match.

Show one possible answer
html
<form id="pw">
  <input id="p1" type="password"> <input id="p2" type="password">
  <button>Save</button>
  <p id="pw-msg"></p>
</form>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("#pw").on("submit", function (event) {
    event.preventDefault();
    if ($("#p1").val() !== $("#p2").val()) {
      $("#pw-msg").text("The passwords do not match.");
      return;
    }
    $("#pw-msg").text("");
    console.log("passwords match");
  });
</script>
result
passwords match

Key points

  • Handle the form's submit event, not the button's click, so pressing Enter is covered too.
  • change fires when a value is committed (a select changes, a checkbox is ticked, a text field is left after editing).
  • blur fires when a field loses focus, a good moment to check what was typed; focus fires when it gains focus.
  • focus and blur do not bubble; focusin and focusout do, which makes them suitable for a handler on the whole form.

Check yourself

1. Why handle submit on the form instead of click on the submit button?
2. When does change fire on a text input?
3. You want one handler on a form that runs when any field inside it loses focus. Which event?
4. In what order do these fire in jQuery 4 when focus moves from field A to field B?