12

考虑一个带有 2 个提交按钮的简单表单

<form method="post">
 <button type="submit" name="command" value="cancel">Cancel Order</button>
 <button type="submit" name="command" value="proceed">Save Order</button>
</form>

提交后,服务器将通过检查command. 伟大的!

在这种情况下,我使用onsubmit表单的事件处理程序来预处理并通过 AJAX 发送表单数据。像这样:<form method="post" onsubmit="return ajaxSubmit(this);">

我使用这个ajaxSubmit函数作为检查任何提供的表单元素并通过 Ajax 发送数据的通用方法。这可以很好地确定文本字段的值,如果复选框被“选中”,在组中选择了哪个收音机等等。它似乎唯一出错的事情(因为我不确定如何检查这个)是哪个提交按钮用于提交表单。即,没有任何内容myForm["command"]可以说明实际使用了 2 个命令按钮中的哪一个。

相反,有没有办法访问服务器在发送之前使用 JavaScript 接收的相同“发布”数据?

否则,这只是我需要解决的缺陷吗?最好的方法是什么?

编辑: 由于所有现代浏览器都会传递用于提交表单的按钮的名称/值(以及其他相关部分,例如从组中选择哪个选项、选中的复选框名称/值等),任何人都可以解释为什么存在在发送到服务器之前没有办法直接访问这些数据吗?我们不能这样做有什么理由吗?

4

4 回答 4

17

相反,有没有办法访问服务器在发送之前使用 JavaScript 接收的相同“发布”数据?

不是那个确切的数据,不。

知道哪个submit按钮被按下的常用方法是(不幸的是)将click处理程序附加到按钮并让它们设置一个变量(或hidden字段的值),然后您可以检查您的submit事件处理程序。

由于您使用的是旧式 DOM0 事件处理程序属性,因此该hidden字段可能更适合您正在执行的操作:

<form method="post">
 <input type="hidden" name="submitclicked" value="">
 <button type="submit" name="command" value="cancel" onclick="submitClick(this);">Cancel Order</button>
 <button type="submit" name="command" value="proceed" onclick="submitClick(this);">Save Order</button>
</form>

...submitClick看起来像这样:

function submitClick(button) {
    button.form.submitclicked.value = button.value;
}

...但我确实建议考虑使用 DOM2 样式的事件处理程序,或者至少在代码块中附加 DOM0 处理程序,因为您可以避免创建全局函数、共享数据而不创建全局变量等。


为了清楚起见,您不必为onclick每个元素指定一个属性,我在上面这样做的唯一原因是因为您使用的是 DOM0 处理程序。

处理它的更好方法是使用事件冒泡。由于click事件从其后代控件(包括提交按钮)冒泡到表单,因此您可以将事件挂接到表单上,然后查看它是否发生在提交按钮上,如果是,那么该按钮value是什么。

例如,这里有一个动态附加到表单的 DOM0 处理程序,它将提醒单击的提交按钮的值:

var form = document.getElementById("theForm");
form.onclick = function(e) {
  // Get the event
  e = e || window.event;

  // Did it originate in an input[type=submit]?
  if (e.target.tagName === "INPUT" &&
      e.target.type === "submit") {
    // Yes
    alert(e.target.value);
  }
};

实例| 资源

或者在任何现代浏览器上使用 DOM2 处理程序(不是 IE8 或更早版本,但很容易添加attachEvent这些处理程序,它的作用大致相同addEventListener[并早于它]):

document.getElementById("theForm").addEventListener("click", function(e) {
  // Did it originate in an input[type=submit]?
  if (e.target.tagName === "INPUT" &&
      e.target.type === "submit") {
    // Yes
    alert(e.target.value);
  }
}, false);

实例| 资源

或者使用一个库来使它更容易(这里是 jQuery,但大多数都有这个功能,称为事件委托):

$("#theForm").delegate("input[type=submit]", "click", function() {
  alert(this.value);
  return false;
});

实例| 来源(我使用delegate那里是因为我喜欢清晰;使用最新版本的 jQuery,您可以使用 hyper-overloaded on,但不太清楚。如果您选择,请注意参数的顺序不同。)

这里的重点是它并不复杂、困难或特别麻烦。

重新编辑您的结束问题:

...谁能解释为什么在发送到服务器之前无法直接访问这些数据?

可能不是,不。重要的是要了解很多这些东西刚刚进化。与表单一起发送的提交按钮的值是 HTML 的东西,显然在执行 DOM HTML 表单模块时,任何人都没有想到“嘿,我们应该在表单上有一个仅在表单期间存在的属性提交事件,告诉您提交表单的内容。” 它可能应该发生在某人身上,但显然,它没有。

于 2012-12-19T11:04:18.600 回答
4

另一种解决方案是使用单选按钮而不是提交按钮(不过,您必须将单选按钮设计为看起来像按钮)。

提交后,该字段的值应该是被点击的那个。您可以使用 jQuery 获取选定的选项$("[name=command]:selected]"),或者$("#theForm").serialize()

<form method="post" onsubmit="return ajaxSubmit(this);" id="theForm">
 <input type="radio" name="command" value="cancel" id="cancel" onClick="document.getElementById('theForm').submit();">
 <label for="cancel">Cancel Order</label>

 <input type="radio" name="command" value="proceed" id="proceed" onClick="document.getElementById('theForm').submit();">
 <label for="proceed">Save Order</label>
</form>
于 2012-12-29T02:52:16.890 回答
2

我认为你可以通过删除另一个按钮来解决这个问题,那个没有被点击的按钮。之后,您可以运行 jQuery 的 serialize(),或者通过任何其他方式访问留下的按钮的值。

代码将是:

<form method="post">
 <button type="submit" id=cancel name="command" value="cancel" onclick="document.getElementByid('submit').remove();submitClick(this);">Cancel Order</button>
 <button type="submit" id=submit name="command" value="proceed" onclick="document.getElementByid('cancel').remove();submitClick(this);">Save Order</button>
</form>
于 2012-12-29T02:37:23.210 回答
1

一切都是合理的,但是如果您要在所有提交按钮上附加点击处理程序,那么通过提交功能的箍来管理您的提交细节就没有多大意义了。

只需让点击处理程序触发表单提交,同时将足够的上下文信息传递给组合。等等,点击处理程序通常已经告诉你点击的来源(有你的上下文信息),尤其是在使用一些 jQuery-ish 框架的情况下。

所以而不是:

<form onsubmit="doSubmit()" ...>
<input type="submit" onclick="updateSourceTo('cancel');" ... />
<input type="submit" onclick="updateSourceTo('submit');" ... />

利用:

<form ...>
<input type="button" onclick="doSubmit('cancel');" ... />
<input type="button" onclick="doSubmit('submit');" ... />

或者,如果您将通过查看点击事件目标来检测源:

<form ...>
<input type="button" onclick="handleSubmitButtonClick();" ... />
<input type="button" onclick="handleSubmitButtonClick();" ... />

对于 handleSubmitButtonClick 的细节,我应该提到form.submit()和 jQuery 的event.target之类的东西。

我承认保持提交时提交范式促进了某种纯粹的表单处理,但 IMO 你已经通过使用两个提交按钮进入了非纯粹的领域。

于 2013-01-02T05:17:23.753 回答