如果我有这样的表格,
<form action="/Car/Edit/17" id="myForm" method="post" name="myForm"> ... </form>
如何在不通过 JavaScript/jQuery 重定向到另一个视图的情况下提交它?
我从 Stack Overflow 中阅读了很多答案,但它们都将我重定向到 POST 函数返回的视图。
您可以通过将表单的
action
重定向到不可见的 <iframe>
来实现此目的。它不需要任何 JavaScript 或任何其他类型的脚本。
<iframe name="dummyframe" id="dummyframe" style="display: none;"></iframe>
<form action="submitscript.php" target="dummyframe">
<!-- Form body here -->
</form>
为了实现你想要的,你需要使用jQuery Ajax,如下所示:
$('#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
}
});
});
也试试这个:
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
}
});
}
这工作完美无缺。我从
Html.ActionLink(...)
调用这个函数
function SubForm (){
$.ajax({
url: '/Person/Edit/@Model.Id/',
type: 'post',
data: $('#myForm').serialize(),
success: function(){
alert("worked");
}
});
}
由于当前所有答案都使用 jQuery 或 iframe 技巧,因此认为仅使用纯 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);
}
在页面底部放置一个隐藏的
iFrame
并将其 target
放入表单中:
<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>
快速又简单。请记住,虽然
target
属性仍然受到广泛支持(并且在 HTML5 中受支持),但它在 HTML 4.01 中已被弃用。
因此,您确实应该使用 Ajax 来面向未来。
好吧,我不会告诉你一种神奇的方法,因为根本不存在。 如果您为表单元素设置了操作属性,它将重定向。
如果您不希望它重定向,只需不要设置任何操作并设置
onsubmit="someFunction();"
在你的
someFunction()
中你可以做任何你想做的事情(无论是否使用AJAX),最后,你添加return false;
来告诉浏览器不要提交表单...
自 2020 年起的单行解决方案,如果您的数据不打算作为
multipart/form-data
或 application/x-www-form-urlencoded
发送:
<form onsubmit='return false'>
<!-- ... -->
</form>
您需要 Ajax 来实现它。像这样的东西:
$(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;
});
});
参见 jQuery 的
post
函数。
我会创建一个按钮,并设置一个
onClickListener
($('#button').on('click', function(){});
),然后在函数中发送数据。
另外,请参阅 jQuery 的
preventDefault
函数!
也可以通过将提交按钮移到表单之外来实现所需的效果,如下所述:
像这样:
<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>
使用此代码片段,您可以提交表单并避免重定向。相反,您可以将成功函数作为参数传递并执行您想做的任何操作。
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)
});
}
然后就做:
var formElement = document.getElementById("yourForm");
submitForm(formElement, function() {
console.log("Form submitted");
});
即发即忘 vanilla js + svelte
function handleSubmit(e) {
const request = new Request(`/products/${item.ItemCode}?_method=PUT`, {
method: 'POST',
body: new FormData(e.target),
});
fetch(request)
}
用于 Svelte:
<form method="post" on:submit|preventDefault={handleSubmit}>
使用 Web 组件,您可以创建一个易于重用的表单组件,可以很好地处理这个问题。
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' }
);
使用示例(与事件有关的所有内容都是可选的):
<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>
使用 HTTP 响应状态代码 204:
204 无内容
HTTP 204 No Content 成功状态响应代码表示请求已成功,但客户端不需要离开当前页面。
例如,在为 wiki 站点实现“保存并继续编辑”功能时可能会使用此功能。在这种情况下,将使用 PUT 请求来保存页面,并且将发送 204 No Content 响应以指示编辑器不应被其他页面替换。
204 响应默认是可缓存的(此类响应中包含 ETag 标头)。
但不幸的是,截至 2024 年中期 它无法在 iOS Safari 中工作。
如果您控制后端,请使用类似
response.redirect
的内容而不是 response.send
。
您可以为此创建自定义 HTML 页面,或者只是重定向到您已有的内容。
在 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)