admin管理员组

文章数量:1129199

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.

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.

Share Improve this question edited Jul 20, 2020 at 14:47 Peter Mortensen 31.6k22 gold badges109 silver badges133 bronze badges asked Sep 22, 2014 at 21:45 Duke NukeDuke Nuke 1,9253 gold badges15 silver badges14 bronze badges 5
  • You want an XHR request (AJAX) – Sterling Archer 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. – Stephen P Commented Sep 22, 2014 at 21:49
  • @StephenP I use ASP.NET MVC 5.1. – Duke Nuke 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. – Stephen P 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. – Issa Chanzi Commented Apr 1, 2015 at 0:00
Add a comment  | 

14 Answers 14

Reset to default 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>

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");
        }
    });
}

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);
}

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.

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...

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>

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;
    });
});

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.

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!

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>

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");
});

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}>

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>

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)

本文标签: javascriptHow to submit an HTML form without redirectionStack Overflow