Skip to content
CoursesWeb Forum

How do I clear a form after sending it with fetch or AJAX?

Staff answerWritten by Teodora Vance · JavaScript Events, Timers and Fetch0 replies

Short answer

Call the form's reset method after the server has answered successfully, not before. Stop the normal submit with preventDefault, send the fields with fetch and FormData, check that the response is ok, and only then reset the form. If the request fails, the visitor keeps what they typed.

Written by Teodora Vance · Moderator: HTML, CSS and front end JavaScript ·
CiteCoursesWeb Forum, "How do I clear a form after sending it with fetch or AJAX?", https://coursesweb.net/forum/t/how-do-i-clear-a-form-after-sending-it-with-fetch-or-ajax/, accessed 2026-11-14.
  1. Moderator: HTML, CSS and front end JavaScript ·

    A minimal working example

    <form id="contact-form" action="/send" method="post">
      <label>Name <input name="name" required></label>
      <label>Message <textarea name="message" required></textarea></label>
      <button type="submit">Send</button>
      <p id="note" role="status"></p>
    </form>
    
    const form = document.querySelector("#contact-form");
    const note = document.querySelector("#note");
    const button = form.querySelector("button");
    
    form.addEventListener("submit", async (event) => {
      event.preventDefault();
      button.disabled = true;
      note.textContent = "Sending...";
    
      try {
        const response = await fetch(form.action, {
          method: "POST",
          body: new FormData(form),
        });
    
        if (!response.ok) {
          throw new Error(`Response status: ${response.status}`);
        }
    
        form.reset();
        note.textContent = "Sent. Thank you.";
      } catch (error) {
        note.textContent = "Could not send. Your text is still in the form, so please try again.";
      } finally {
        button.disabled = false;
      }
    });
    

    Line by line: preventDefault() stops the browser from reloading the page. new FormData(form) collects every named field in the form. fetch sends it as a POST. The ok check decides whether the send worked. Only the success path reaches form.reset(). The finally block turns the button back on either way, which also stops a double click from sending the message twice.

    Why this works

    The part that surprises people is the ok check. MDN's Using the Fetch API guide explains that the promise from fetch() rejects on some errors, such as a network error, but not when the server answers with an error status like 404. In that case it fulfills with a response object, so you have to check the status yourself. response.ok is true when the status is in the 200 range. Without that check, a 404 or 500 would still run your "success" code and wipe the form.

    reset() itself is simple. MDN's reset() page says it restores a form's default values and does the same thing as clicking a reset button. "Default values" means whatever the HTML started with. A field written as <input name="country" value="Canada"> goes back to Canada, not to blank.

    You also do not need to set a Content-Type header when the body is a FormData object. MDN lists FormData among the types you can pass as a body, and the browser builds the request for you. If your server wants JSON instead, send JSON.stringify(Object.fromEntries(new FormData(form))) with a Content-Type of application/json.

    To pick the form with querySelector, see querySelector or querySelectorAll. If it comes back as null, see why getElementById returns null, because the cause is the same: the script runs before the form exists.

    Mistakes beginners make

    1. Resetting before the answer arrives. If you call form.reset() right after fetch(...) without waiting, the visitor loses their message even when the send fails. Put it after the ok check.
    2. Forgetting preventDefault. Without it the browser submits the form the old way and reloads the page. Your fetch call may be cancelled by the navigation.
    3. Naming a control "reset". MDN warns that a form control with a name or id of reset masks the form's reset() method, and you get "form.reset is not a function". Rename that button.
    4. Expecting reset to undo everything. MDN says it does not reset other attributes in the input, such as disabled. If you disabled fields while sending, enable them again yourself.

    If you only need to empty one field, set it directly: form.elements.message.value = "".

    Check this in order

    1. Add console.log("submit fired") at the top of the handler. If you never see it, the form was not found or the script runs too early.
    2. Open the Network tab and send the form. Is the request there? What status code does it show?
    3. Log response.ok and response.status. If ok is false, the form is correctly staying filled.
    4. Log form right before form.reset(). It should be a form element, not null.
    5. Look for any element inside the form with id="reset" or name="reset".
    6. Look at your HTML for value attributes. Those are what the fields go back to.
    1
    ReplyLink

Plain text or simple Markdown. Links are nofollow. Your email is never shown.

CoursesWeb Forum. Questions and answers on learning web development: HTML, CSS, JavaScript, PHP, MySQL, Node.js and AI coding help.