165

If I have a form like this,

<form action="/Car/Edit/17" id="myForm" method="post" name="myForm"> ... </form> 

how can I submit it without redirecting to another view by JavaScript/jQuery?

I read plenty of answers from Stack Overflow, but all of them redirect me to the view returned by the POST function.

5
  • You want an XHR request (AJAX) Commented Sep 22, 2014 at 21:47
  • 4
    XHR / AJAX is one way — it submits the post and gets the response behind the scenes, so the browser never leaves the page it's on. Another way is a server-side redirect after processing the post, which depends on what server technology you're using. Commented Sep 22, 2014 at 21:49
  • @StephenP I use ASP.NET MVC 5.1. Commented Sep 22, 2014 at 21:56
  • @Duke, all I'm saying is there is more than one approach (ajax vs. server-redirect) and your choice depends on your needs. Modern sites will most likely want to do ajax. Note also that all these answers are saying you need jQuery — jQuery's great but there are, in fact, other ways to do ajax... though I would indeed use jQuery myself. Commented Sep 22, 2014 at 22:09
  • 1
    My way is simple clean and elegant, and it's only 2 lines of code. It uses no scripts, and works in HTML4 and above, even if JavaScript is turned off. Commented Apr 1, 2015 at 0:00

14 Answers 14

195

You can achieve that by redirecting the form's action to an invisible <iframe>. It doesn't require any JavaScript or any other type of scripts.

<iframe name="dummyframe" id="dummyframe" style="display: none;"></iframe> <form action="submitscript.php" target="dummyframe"> <!-- Form body here --> </form> 
Sign up to request clarification or add additional context in comments.

6 Comments

This is great. But how can I do something, after the form is submitted? i.e. The form's textfields will have to be empty, the focus goes back to the first field, etc. ?
There some kind of javascript that can do that. Just change the <input type='submit'... to <input type='reset' and add onclick='document.forms["myForm"].submit();'>
Be careful, it is likely to reload the page your form is in into the iframe, which can cause performance troubles if you're building an app or a big website.
Notice that form target should be same as iframe name
I still see, when submitting the form, that elements for the parent page, that the iframe doesn't need, reloading.
|
100

In order to achieve what you want, you need to use jQuery Ajax as below:

$('#myForm').submit(function(e){ e.preventDefault(); $.ajax({ url: '/Car/Edit/17/', type: 'post', data:$('#myForm').serialize(), success:function(){ // Whatever you want to do after the form is successfully submitted } }); }); 

Also try this one:

function SubForm(e){ e.preventDefault(); var url = $(this).closest('form').attr('action'), data = $(this).closest('form').serialize(); $.ajax({ url: url, type: 'post', data: data, success: function(){ // Whatever you want to do after the form is successfully submitted } }); } 

Final solution

This worked flawlessly. I call this function from Html.ActionLink(...)

function SubForm (){ $.ajax({ url: '/Person/Edit/@Model.Id/', type: 'post', data: $('#myForm').serialize(), success: function(){ alert("worked"); } }); } 

5 Comments

This worked great the problem is that I don't want it to be automatically(always) submited this way. I would like to have a function with a name to do this stuff you posted in your answer. So I can invoke it manually when I want to, to make it post the form. Like below I can give the name of the function to invoke. @Html.ActionLink("Add a Report", "Create", "Reports", new { carId = Model.Id }, new { onclick = "FUNCTION_WHICH_SUBMITES_FORM()" })
This worked: function SubForm (){ alert("1"); //e.preventDefault(); $.ajax({ url:'/Car/Edit/@Model.Id/', type:'post', data:$('#myForm').serialize(), success:function(){ alert("fasf"); } }); }
For some reason your second solution did not work, but the one I posted in last comment did. I will add my solution to your post cause only because of you I could achieve this.
the second one must work as well, there might be something else to it, but if you found the solution we don't need to go down that road right now! glad it helped ;)
Thanks this answer also helped me put a custom text in place of the form after submission
66

Since all current answers use jQuery or tricks with iframe, figured there is no harm to add method with just plain JavaScript:

function formSubmit(event) { var url = "/post/url/here"; var request = new XMLHttpRequest(); request.open('POST', url, true); request.onload = function() { // request successful // we can use server response to our request now console.log(request.responseText); }; request.onerror = function() { // request failed }; request.send(new FormData(event.target)); // create FormData from form that triggered event event.preventDefault(); } // and you can attach form submit event like this for example function attachFormSubmitEvent(formId){ document.getElementById(formId).addEventListener("submit", formSubmit); } 

2 Comments

I tip my hat to you. I've spent hours trying to figure out how to get jquery to send a form to an nginx backend with the contentType=false parameter and always get a 415 as a result. This was the only solution I found that solved my particular problem.
If you're trying to do it with fetchAPI, there is an existing Q&A as well: stackoverflow.com/a/46642899
39

Place a hidden iFrame at the bottom of your page and target it in your form:

<iframe name="hiddenFrame" width="0" height="0" border="0" style="display: none;"></iframe> <form action="/Car/Edit/17" id="myForm" method="post" name="myForm" target="hiddenFrame"> ... </form> 

Quick and easy. Keep in mind that while the target attribute is still widely supported (and supported in HTML5), it was deprecated in HTML 4.01.

So you really should be using Ajax to future-proof.

1 Comment

According MDN, this behavior for the target is completely valid, so AJAX is still optional.
15

Okay, I'm not going to tell you a magical way of doing it because there isn't. If you have an action attribute set for a form element, it will redirect.

If you don't want it to redirect simply don't set any action and set onsubmit="someFunction();"

In your someFunction() you do whatever you want, (with AJAX or not) and in the ending, you add return false; to tell the browser not to submit the form...

1 Comment

There is a magical way of doing it. Set a target attribute so the form redirects to somewhere other than the current frame. If you add an invisible iframe for things like this in your pages. It's pretty simple.
7

One-liner solution as of 2020, if your data is not meant to be sent as multipart/form-data or application/x-www-form-urlencoded:

<form onsubmit='return false'> <!-- ... --> </form> 

2 Comments

If you combine this with the OP's action="...", this effectively prevents the page switch, but also prevents data being submitted across the network.
@Kev I personally send my data via JS XHR, that's why I don't want page redirection, cause it's a JS app
6

Use HTTP response status code 204:

204 No Content

The HTTP 204 No Content success status response code indicates that a request has succeeded, but that the client doesn't need to navigate away from its current page.

This might be used, for example, when implementing "save and continue editing" functionality for a wiki site. In this case a PUT request would be used to save the page, and the 204 No Content response would be sent to indicate that the editor should not be replaced by some other page.

A 204 response is cacheable by default (an ETag header is included in such a response).

Unfortunately, though, as of mid-2024 it does not work in iOS Safari.

In October 2024, the issue was fixed in WebKit, so hopefully the 204 status code will soon work as expected in iOS Safari.

1 Comment

this should be the preferred answer - we should use more of the core functionalities
4

You need Ajax to make it happen. Something like this:

$(document).ready(function(){ $("#myform").on('submit', function(){ var name = $("#name").val(); var email = $("#email").val(); var password = $("#password").val(); var contact = $("#contact").val(); var dataString = 'name1=' + name + '&email1=' + email + '&password1=' + password + '&contact1=' + contact; if(name=='' || email=='' || password=='' || contact=='') { alert("Please fill in all fields"); } else { // Ajax code to submit form. $.ajax({ type: "POST", url: "ajaxsubmit.php", data: dataString, cache: false, success: function(result){ alert(result); } }); } return false; }); }); 

Comments

2

See jQuery's post function.

I would create a button, and set an onClickListener ($('#button').on('click', function(){});), and send the data in the function.

Also, see the preventDefault function, of jQuery!

Comments

1

The desired effect can also be achieved by moving the submit button outside of the form as described here:

Prevent page reload and redirect on form submit ajax/jquery

Like this:

<form id="getPatientsForm"> Enter URL for patient server <br/><br/> <input name="forwardToUrl" type="hidden" value="/WEB-INF/jsp/patient/patientList.jsp" /> <input name="patientRootUrl" size="100"></input> <br/><br/> </form> <button onclick="javascript:postGetPatientsForm();">Connect to Server</button> 

Comments

1

Using this snippet, you can submit the form and avoid redirection. Instead you can pass the success function as argument and do whatever you want.

function submitForm(form, successFn){ if (form.getAttribute("id") != '' || form.getAttribute("id") != null){ var id = form.getAttribute("id"); } else { console.log("Form id attribute was not set; the form cannot be serialized"); } $.ajax({ type: form.method, url: form.action, data: $(id).serializeArray(), dataType: "json", success: successFn, //error: errorFn(data) }); } 

And then just do:

var formElement = document.getElementById("yourForm"); submitForm(formElement, function() { console.log("Form submitted"); }); 

Comments

0

Fire and forget vanilla js + svelte

function handleSubmit(e) { const request = new Request(`/products/${item.ItemCode}?_method=PUT`, { method: 'POST', body: new FormData(e.target), }); fetch(request) } 

Used in Svelte:

<form method="post" on:submit|preventDefault={handleSubmit}> 

Comments

-1

Using web components you can create an easily reusable form component that handles this nicely.

function urlencodeFormData(fd: FormData) { let s = ''; function encode(s: string) { return encodeURIComponent(s).replace(/%20/g, '+'); } const formData: [string, string][] = []; fd.forEach((value, key) => { if (value instanceof File) { formData.push([key, value.name]); } else { formData.push([key, value]); } }); for (const [key, value] of formData) { s += (s ? '&' : '') + encode(key) + '=' + encode(value); } return s; } const xhrOnSubmit = (event: SubmitEvent) => { console.log('Form submitted'); const form: HTMLFormElement | null = event.target instanceof HTMLFormElement ? event.target : null; if (form == null) { console.error('Event target of form listener is not a form!'); return; } let baseUrl = form.action; if (baseUrl == null || baseUrl === '') { baseUrl = window.location.href; } const requestUrl = new URL(baseUrl, window.location.href); const shouldClear = form.getAttribute('data-clear-form') === 'true'; // Decide on encoding const formenctype = event.submitter?.getAttribute('formenctype') ?? event.submitter?.getAttribute('formencoding'); const enctype = formenctype ?? form.getAttribute('enctype') ?? form.getAttribute('encoding') ?? 'application/x-www-form-urlencoded'; // Decide on method let formMethod = event.submitter?.getAttribute('formmethod') ?? form.getAttribute('method')?.toLowerCase() ?? 'get'; const formData = new FormData(form); // Encode body let body: BodyInit | null = null; if (formMethod === 'get') { requestUrl.search = new URLSearchParams( urlencodeFormData(formData) ).toString(); } else if (formMethod === 'post') { if (enctype === 'application/x-www-form-urlencoded') { body = urlencodeFormData(formData); } else if (enctype === 'multipart/form-data') { body = formData; } else if (enctype === 'text/plain') { let text = ''; // @ts-ignore - FormData.entries() is not in the TS definition for (const element of formData.keys()) { text += `${element}=${JSON.stringify(formData.get(element))}\n`; } } else { throw new Error(`Illegal enctype: ${enctype}`); } } else if (formMethod === 'dialog') { // Allow default behavior return; } else { throw new Error(`Illegal form method: ${formMethod}`); } // Send request const requestOptions: RequestInit = { method: formMethod, headers: { 'Content-Type': enctype, }, }; if (body != null && formMethod === 'post') { requestOptions.body = body; } const response = fetch(baseUrl, requestOptions).then((response) => { if (shouldClear) { form.reset(); } if (response.ok) { form.dispatchEvent( new CustomEvent('xhr-form-success', { detail: response, }) ); } else { form.dispatchEvent( new CustomEvent('xhr-form-failure', { detail: response, }) ); } return response; }); event.preventDefault(); }; customElements.define( 'xhr-form', class extends HTMLFormElement { constructor() { console.log('Form constructed'); super(); } connectedCallback() { this.addEventListener('submit', xhrOnSubmit); } disconnectedCallback() { this.removeEventListener('submit', xhrOnSubmit); } }, { extends: 'form' } ); 

An example of use (everything to do with the events is optional):

<form action="/printer" method="post" id="xhr-form" is="xhr-form"> <h2>XHR POST Test</h2> <input type="text" name="name" placeholder="Name"> <input type="number" name="age" placeholder="Age"> <input type="submit" value="Submit"> </form> <script> const xhrForm = document.getElementById('xhr-form'); xhrForm.addEventListener('xhr-form-success', (event) => { console.log('XHR Form Success', event.detail); }); xhrForm.addEventListener('xhr-form-failure', (event) => { console.log('XHR Form Failure', event.detail); }); </script> 

Comments

-2

If you control the back end, then use something like response.redirect instead of response.send.

You can create custom HTML pages for this or just redirect to something you already have.

In Express.js:

const handler = (req, res) => { const { body } = req handleResponse(body) .then(data => { console.log(data) res.redirect('https://yoursite.com/ok.html') }) .catch(err => { console.log(err) res.redirect('https://yoursite.com/err.html') }) } ... app.post('/endpoint', handler) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.