How do I clear a form after sending it with fetch or AJAX?
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.
Cite
CoursesWeb 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.- Teodora VanceStaffModerator: 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.fetchsends it as a POST. Theokcheck decides whether the send worked. Only the success path reachesform.reset(). Thefinallyblock 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
okcheck. MDN's Using the Fetch API guide explains that the promise fromfetch()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.okistruewhen 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-Typeheader when the body is aFormDataobject. MDN listsFormDataamong the types you can pass as a body, and the browser builds the request for you. If your server wants JSON instead, sendJSON.stringify(Object.fromEntries(new FormData(form)))with aContent-Typeofapplication/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
- Resetting before the answer arrives. If you call
form.reset()right afterfetch(...)without waiting, the visitor loses their message even when the send fails. Put it after theokcheck. - Forgetting preventDefault. Without it the browser submits the form the old way and reloads the page. Your
fetchcall may be cancelled by the navigation. - Naming a control "reset". MDN warns that a form control with a name or id of
resetmasks the form'sreset()method, and you get "form.reset is not a function". Rename that button. - 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
- 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. - Open the Network tab and send the form. Is the request there? What status code does it show?
- Log
response.okandresponse.status. Ifokis false, the form is correctly staying filled. - Log
formright beforeform.reset(). It should be a form element, not null. - Look for any element inside the form with
id="reset"orname="reset". - Look at your HTML for
valueattributes. Those are what the fields go back to.
- Resetting before the answer arrives. If you call
Write something first.
Give people something to work with: at least 30 words on what happened and what you tried.
That is too long. Keep it under 6,000 characters.
Write the question as the title, 15 to 140 characters, no links.
Pick a category.
Add a name (2 to 40 characters, no links).
That email address does not look right.
That was quick. Read the thread, then try again.
The form expired. Reload the page and post again.
Something went wrong with the form. Reload and try again.
Please complete the check and post again.
Limit reached for now. Try again later.
This thread is closed to new replies.
This thread no longer accepts replies.
Something went wrong with the form. Reload and try again.
Post a reply or question first (name and email), then this browser can vote, edit and accept answers.
You cannot vote on your own post.
Only the author (within 30 days) or the forum team can do that.
That email already has an account. Use your sign-in link instead.
New accounts are paused for the moment. Try again later.
That was already posted.