Suggest an editImprove this articleRefine the answer for “Cancelling form submission”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**To stop a form from submitting the default way, subscribe to the form's own `submit` event and call `event.preventDefault()` inside the handler.** After that the browser makes no HTTP request to the `action` URL and does not reload the page, so you can collect the values with `new FormData(form)` and send them yourself with `fetch`. Listen to `submit` on the form, not to `click` on the button, because a form is also submitted by pressing Enter inside a field. ```javascript const form = document.querySelector('#loginForm'); form.addEventListener('submit', (event) => { event.preventDefault(); }); ``` **Key point:** call `event.preventDefault()` in the form's `submit` handler, not in the button's `click` handler.Shown above the full answer for quick recall.Answer (EN)Image**A form's default submission is cancelled by calling `event.preventDefault()` in the `submit` event handler.** After that the browser makes no request to `action` and does not reload the page, so you handle the data yourself, usually with `fetch`. ## Theory ### TL;DR - By default `submit` collects the fields, sends an HTTP request to `action` and reloads the page. - `event.preventDefault()` inside the `submit` handler cancels that default behaviour. - The form values are easiest to read with `new FormData(form)` and `Object.fromEntries(formData.entries())`. - The request is then sent manually: `fetch()` or any HTTP client. - Listen to `submit` on the form, not to `click` on the button: a form is also submitted by Enter inside a field. - The inline `onsubmit` attribute works too, but it mixes markup with logic and is not recommended. ### Quick example ```javascript const form = document.querySelector('#loginForm'); form.addEventListener('submit', (event) => { event.preventDefault(); // cancel the default submission console.log('The form does not reload the page!'); }); ``` ### The default behaviour of a form ```html <form id="loginForm" action="/login" method="post"> <input name="username" /> <button type="submit">Log in</button> </form> ``` By default, when the user presses "Log in": - the browser collects every field of the form; - makes an HTTP request (usually POST) to `/login`; - and **reloads the page**. That reload is exactly what breaks any SPA scenario: the application state is lost, and the response cannot be shown without rendering a whole new page. ### How to cancel the default submission Call `event.preventDefault()` in the `submit` event handler: ```javascript const form = document.querySelector('#loginForm'); form.addEventListener('submit', (event) => { event.preventDefault(); // cancel the default submission console.log('The form does not reload the page!'); }); ``` Now the browser **will not reload**, and you can process the data yourself, for example with `fetch` or any HTTP library. ### Example with asynchronous handling ```html <form id="form"> <input name="email" type="email" placeholder="Email" required /> <input name="password" type="password" placeholder="Password" required /> <button>Log in</button> </form> <script> const form = document.querySelector('#form'); form.addEventListener('submit', async (e) => { e.preventDefault(); // cancel the default behaviour const formData = new FormData(form); const data = Object.fromEntries(formData.entries()); console.log('Sending through JS:', data); const res = await fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }); const result = await res.json(); console.log('Server response:', result); }); </script> ``` What happens here: - the form does not reload; - the values are taken from the fields through `FormData`; - the request goes out asynchronously through `fetch`; - the result can be shown right on the page. ### Alternative: the onsubmit attribute in HTML ```html <form onsubmit="event.preventDefault(); alert('No reload!')"> <input placeholder="Name" /> <button>Send</button> </form> ``` This works, but it is **not recommended**: mixing JS and HTML makes the code harder to maintain, prevents reusing the handler and does not play well with a Content Security Policy. ### Summary table | What you want to do | The right way | | --- | --- | | Cancel the page reload | `event.preventDefault()` in the `submit` handler | | Read the form data | `new FormData(form)` | | Send the data manually | `fetch()` or the HTTP client of your choice | | The reliable approach | Listen to `submit`, not to `click` | > **Just remember:** so that the form does not reload the page, always use > > ```javascript > form.addEventListener('submit', (e) => e.preventDefault()); > ``` ### Common mistakes - Cancelling the submission in the button's `click` handler: `button.addEventListener('click', (e) => e.preventDefault())`. That does not guarantee the form will not submit, because pressing Enter inside a field also fires `submit`. - Forgetting `event.preventDefault()` and then wondering why the page flashes and the application state resets. - Attaching the handler before the form exists in the DOM: `document.querySelector('#form')` returns `null` and `addEventListener` throws. - Using `return false` in a listener added through `addEventListener`. It does nothing there, unlike in the old inline handlers. - Calling `preventDefault()` after an `await`: by then the browser has already acted on the event, so the cancellation must be the first thing the handler does. - Reading every field by hand with `document.querySelector` instead of `FormData`, and losing checkboxes and repeated field names in the process.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.