ChatGPT解决这个技术问题 Extra ChatGPT

一个表单中的两个提交按钮

我在一个表单中有两个提交按钮。我如何确定哪一个被击中服务器端?

考虑将接受的答案更改为 Parrots' answer
@PeterMortensen - 今天接受的答案和 Parrot 的答案都不是最好的。有关使用属性 formaction 的较新 HTML5 解决方案,请参阅 Leo's answer。或者参见 kiril's answer,了解如何让用户可见的 HTML 独立于发送到浏览器的值 - 以比 Greg 或 Parrot 的答案更易于编码的方式解决国际化问题。

T
ToolmakerSteve

解决方案 1:给每个输入一个不同的值并保持相同的名称:

<input type="submit" name="action" value="Update" />
<input type="submit" name="action" value="Delete" />

然后在代码中检查是否触发了:

if ($_POST['action'] == 'Update') {
    //action for update here
} else if ($_POST['action'] == 'Delete') {
    //action for delete
} else {
    //invalid action!
}

问题在于您将逻辑与输入中的用户可见文本联系起来。

解决方案 2:给每个人一个唯一的名称并检查 $_POST 是否存在该输入:

<input type="submit" name="update_button" value="Update" />
<input type="submit" name="delete_button" value="Delete" />

在代码中:

if (isset($_POST['update_button'])) {
    //update action
} else if (isset($_POST['delete_button'])) {
    //delete action
} else {
    //no button pressed
}

出于 i18n 的目的,使用选定的答案可能会更好。
@LaszloPapp 正如答案本身所说,如果您使用上面选择的答案,您可以在不影响逻辑的情况下将表单国际化(即翻译成不同的语言或方言)。如果您在此答案中使用第一个选项,则逻辑取决于表单实际呈现的语言。
@RobinGreen:我认为大多数人会使用第二种逻辑,不是吗?
i18n = i[ninternationalization]n,18代表第一个和最后一个之间的18个字母。
OP没有要求PHP。
G
Greg

如果你给每个人一个名字,点击的那个将作为任何其他输入发送。

<input type="submit" name="button_1" value="Click me">

还要确保按钮的名称具有正确的名称!例如“button-1”将不起作用。可能会为某人省去很多麻烦,所以请记住这一点。
通常,表单中的所有输入都与表单一起发送。由于仅在单击时才提交按钮的值,因此您必须在表单值中搜索这些预定义名称。我认为另一个答案(stackoverflow.com/a/21778226/88409)涉及给它们都赋予相同的名称,具有不同的值,更有意义。然后,您只需获取单个已知表单字段名称下的值。这也使得对于给定的输入名称只会发送一个值(单击的值)变得更加明显,就像单选按钮的工作方式(相同的名称,不同的值)。
@Triynko,正如 Robin Green 在该答案的评论中所说,这个更适合国际化。例如,如果页面以西班牙语呈现,则按钮的文本可能会有所不同。因此,在这种情况下,让您的代码逻辑依赖于该按钮的文本将会中断。使用名称更安全,因为它是一个不向用户显示的值,因此可以更多地被视为“私有”变量,而不是作为给用户的消息。
澄清@sfarbota 的评论:Parrot 的答案中显示的第一个解决方案是有问题的,因为它依赖于测试用户可见的值。这是可疑的 - 更改用户可见单词时中断的代码被认为是“脆弱的”。 Parrot 的答案中显示的第二种解决方案很好 - 它与这个相同。 Parrot 的第二个解决方案也显示了要编写的相应代码,因此它是一个比这个更有用的答案。
有关使用属性 formaction 的较新 HTML5 解决方案,请参阅 Leo's answer。或者参见 kiril's answer,了解如何让用户可见的 HTML 独立于发送到浏览器的值 - 解决国际化问题。
T
ToolmakerSteve

一个更好的解决方案包括使用按钮标签来提交表单:

<form>
    ...
    <button type="submit" name="action" value="update">Update</button>
    <button type="submit" name="action" value="delete">Delete</button>
</form>

HTML inside 按钮(例如 ..>Update<.. 是用户可以看到的;因为提供了 HTML,所以 value 用户不可见;它只发送到服务器。这种方式没有国际化和多种显示语言的不便(在前一种方案中,按钮的标签也是发送给服务器的值)。


显然浏览器行为不同;有些提交 value 属性,有些提交标签之间的字符串......所以要小心这个。
我认为完全支持提供的代码段 (w3schools.com/tags/att_button_type.asp)
@kiril 该链接中的代码段使用两种不同类型的 <button>submitreset。请注意,reset 不提交任何内容,它只是重置表单。所以杰伦的论点仍然存在。
好吧,你的权利。然后,我查看了 HTML5 W3C 工作草案。引用: >>value 属性为表单提交提供元素的值。元素的值是元素的 value 属性的值,如果有,则为空字符串,否则为空字符串。 >>注意:如果按钮本身用于启动表单提交,则按钮(及其值)仅包含在表单提交中。
@杰罗恩公牛。哪些浏览器提交标签之间的文本?输入或按钮只应提交“值”属性。一个按钮实际上可以在它的标签之间有任何东西,包括图像或其他 HTML 标签。这就是在输入元素上使用按钮的全部意义,并且您试图建议浏览器将所有这些内容作为值转储?没门。
P
Peter Mortensen

对此有一种新的 HTML5 方法,即 formaction 属性:

<button type="submit" formaction="/action_one">First action</button>
<button type="submit" formaction="/action_two">Second action</button>

显然这在 Internet Explorer 9 和更早版本中不起作用,但对于其他浏览器应该没问题(参见:w3schools.com HTML <button> formaction Attribute)。

就个人而言,我通常使用 JavaScript 远程提交表单(以获得更快的感知反馈),并以这种方法作为备份。在这两者之间,唯一没有涉及到的是禁用 JavaScript 的版本 9 之前的 Internet Explorer。

当然,如果您基本上在服务器端执行相同的操作,而不管按下哪个按钮,这可能是不合适的,但通常如果有两个用户端操作可用,那么它们也会映射到两个服务器端操作。

正如 Pascal_dher 在评论中所指出的,此属性也可用于 <input> 标记。


也可用于“输入”标签。根据 w3schools:当使用按钮标签时,不同的浏览器可能会提交不同的值:w3schools.com/tags/tag_button.asp
Rails 用户注意:如果您的表单是使用 form_tag 创建的,则添加此属性将不起作用。我让它工作的唯一方法是切换到 form_for 并使用 f.submit formaction: 'your_path'
P
Peter Mortensen

这非常容易测试:

<form action="" method="get">
    <input type="submit" name="sb" value="One">
    <input type="submit" name="sb" value="Two">
    <input type="submit" name="sb" value="Three">
</form>

只需将其放入 HTML 页面,单击按钮,然后查看 URL。


在这里使用 GET 是一种不好的做法,应该尽可能使用 POST。
@Syncrossus 那是为了测试目的。
P
Peter Mortensen

使用 formaction HTML 属性(第 5 行):

<form action="/action_page.php" method="get">
    First name: <input type="text" name="fname"><br>
    Last name: <input type="text" name="lname"><br>
    <button type="submit">Submit</button><br>
    <button type="submit" formaction="/action_page2.php">Submit to another page</button>
</form>

这类似于 Leo's earlier answer
@ToolmakerSteve - 但是用户已经投票了。任你选!!
M
MevlütÖzdemir
<form>
    <input type="submit" value="Submit to a" formaction="/submit/a">
    <input type="submit" value="submit to b" formaction="/submit/b">    
</form>

HTML5 功能。在最近的网络浏览器上完美运行,谢谢!
注意:这似乎与 Leo's earlier answer 相同,只是它显示使用 input 标记而不是 button 标记。
P
Peter Mortensen

处理多个提交按钮的最佳方法是在服务器脚本中使用 switch case

<form action="demo_form.php" method="get">

    Choose your favorite subject:

    <button name="subject" type="submit" value="html">HTML</button>
    <button name="subject" type="submit" value="css">CSS</button>
    <button name="subject" type="submit" value="javascript">JavaScript</button>
    <button name="subject" type="submit" value="jquery">jQuery</button>
</form>

服务器代码/服务器脚本 - 您提交表单的位置:

文件 demo_form.php

<?php
    switch($_REQUEST['subject']) {

        case 'html': // Action for HTML here
                     break;

        case 'css': // Action for CSS here
                    break;

        case 'javascript': // Action for JavaScript here
                           break;

        case 'jquery': // Action for jQuery here
                       break;
    }
?>

来源:W3Schools.com


是的,您必须了解操作脚本(服务器端脚本技术)您可以使用任何脚本/文件来处理提交的数据,例如 php、asp、jsp 等。<form action="demo_form.php" method="get">
好的。这很令人困惑,因为还有一种名为 ActionScript 的语言。您应该说:“服务器代码”或“服务器脚本”。
我不知道你可以用按钮做到这一点
提交页面通常使用method="POST"
有一个错误,它说: C:\xampp\htdocs\Test-1\index.php 中未定义的数组键“主题”
P
Peter Mortensen

也许这里建议的解决方案在 2009 年有效,但我已经测试了所有这些赞成的答案,没有人在任何浏览器中工作。

我发现唯一可行的解决方案是这个(但我认为使用起来有点难看):

<form method="post" name="form">
    <input type="submit" value="dosomething" onclick="javascript: form.action='actionurl1';"/>
    <input type="submit" value="dosomethingelse" onclick="javascript: form.action='actionurl2';"/>
</form>

为什么不直接使用 formaction="actionurl1"?你不需要 JavaScript。
@rybo111 IE9 浏览器(witch 还是比较广泛使用的)不支持 formaction
@inaliaghle 没错,它大约占用户的 1%——这取决于项目的目标人群。大约 1% 的用户不使用 JavaScript。
对于未来的读者:使用 javascript 没有任何问题,就像在这个答案中一样。这是一项有用的技能。 OTOH,投票率更高的答案也可以正常工作-忽略此答案的前导句。如果由于某种原因您无法获得其他答案,请将您的完整代码发布为 SO 问题,解释发生了什么(或没有发生),并询问您做错了什么。
P
Peter Mortensen

您在一个表单示例中为多个提交按钮形成操作:

 <input type="submit" name="" class="btn action_bg btn-sm loadGif" value="Add Address" title="" formaction="/addAddress"> 
 <input type="submit" name="" class="btn action_bg btn-sm loadGif" value="update Address" title="" formaction="/updateAddress"> 

这是不可理解的。例如,“You formaction”是什么意思?是不是少了一个字?请通过 editing (changing) your answer 回复,而不是在评论中(没有“编辑:”、“更新:”或类似内容 - 答案应该看起来好像是今天写的)。
@PeterMortensen“formaction”代表“表单动作”,它是一个替换默认表单动作的属性。如果您没有为提交按钮声明“formaction”,则表单将使用其默认路由。如果你这样做,它将使用特定的路线。您可以在此处阅读更多信息:w3schools.com/tags/att_input_formaction.asp
P
Peter Mortensen

一个 HTML 示例,用于在不同的按钮单击时发送不同的表单操作:

<form action="/login" method="POST">
    <input type="text" name="username" value="your_username" />
    <input type="password" name="password" value="your_password" />
    <button type="submit">Login</button>
    <button type="submit" formaction="/users" formmethod="POST">Add User</button>
</form>

相同的表单用于添加新用户和登录用户。


从来没想过有这个
P
Peter Mortensen

name 定义为 array

<form action='' method=POST>
    (...) some input fields (...)
    <input type=submit name=submit[save] value=Save>
    <input type=submit name=submit[delete] value=Delete>
</form>

示例服务器代码(PHP):

if (isset($_POST["submit"])) {
    $sub = $_POST["submit"];

    if (isset($sub["save"])) {
        // Save something;
    } elseif (isset($sub["delete"])) {
        // Delete something
    }
}

elseif 非常重要,因为如果没有,两者都会被解析。


现在这是一个很好的建议 — 主要是因为您可以非常轻松地添加更多带有更多案例的按钮,如果添加了按钮但忘记将其添加到 switch(和/或拼写错误的东西等)
此外,@Pato 添加了一个可能更惯用的 similar answer,但你的工作正常!
@GwynethLlewelyn 我没有看到其他答案,或者我写自己的答案时没有注意到。它实际上是相同的,但这只是强调大多数人更喜欢这种逻辑。区别只是出于语义原因的名称,对于新手或任何喜欢从它开始的人的良好理解。
这会通过 HTML 验证吗?例如没有引号?
重新“将名称定义为数组”:您能否详细说明,包括有关此数组事物/约定/语法(特定于 PHP?)的官方文档的链接? (但没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的。)
P
Peter Mortensen

由于您没有指定您使用的服务器端脚本方法,因此我将使用 CherryPy 为您提供一个适用于 Python 的示例(尽管它也可能对其他上下文有用):

<button type="submit" name="register">Create a new account</button>
<button type="submit" name="login">Log into your account</button>

您可以使用名称(使用 <button> 标记而不是 <input>),而不是使用该值来确定按下了哪个按钮。这样,如果您的按钮碰巧有相同的文本,就不会造成问题。所有表单项的名称(包括按钮)都作为 URL 的一部分发送。

在 CherryPy 中,每一个都是执行服务器端代码的方法的参数。因此,如果您的方法的参数列表只有 **kwargs(而不是繁琐地输入每个表单项的每个名称),那么您可以检查查看按下了哪个按钮,如下所示:

if "register" in kwargs:
    pass # Do the register code
elif "login" in kwargs:
    pass # Do the login code

P
Peter Mortensen
<form method="post">
    <input type="hidden" name="id" value="'.$id.'" readonly="readonly"/>'; // Any value to post PHP
    <input type='submit' name='update' value='update' formAction='updateCars.php'/>
    <input type='submit' name='delete' value='delete' formAction='sqlDelete.php'/>
</form>

这是什么? php?这看起来不像是有效的 PHP。是heredoc吗?在任何情况下,都需要一个解释。例如,想法/要点是什么?请通过 editing (changing) your answer 回复,而不是在评论中(没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的)。
P
Peter Mortensen

我认为您应该能够读取 GET 数组中的名称/值。我认为未点击的按钮不会出现在该列表中。


您很可能是指 POST 数组。
不一定,如果表单的方法是“POST”,它就不会出现在 GET 数组中。大多数表单都是通过 POST 提交的。
要么/或在技术上是正确的,但却是错误的。您可以使用 method="GET" 提交表单,但它是令人畏惧的。
只有在使用不当时才会“令人畏惧”:w3.org/2001/tag/doc/whenToUseGet.html
是的,我不是想建议 GET,我只是想概括一下。
P
Peter Mortensen

你也可以这样做(我认为如果你有 N 个输入会很方便)。

<input type="submit" name="row[456]" value="something">
<input type="submit" name="row[123]" value="something">
<input type="submit" name="row[789]" value="something">

一个常见的用例是为每个按钮使用来自数据库的不同 ID,这样您以后可以在服务器中知道单击了哪一行。

在服务器端(本例中为 PHP),您可以将“行”作为数组读取以获取 id。

$_POST['row'] 将是一个只有一个元素的数组,格式为 [ id => value ](例如:[ '123' => 'something' ])。

因此,为了获得点击的 id,您可以:

$index = key($_POST['row']);

key


这类似于@Thelicious posted 的答案,但您的答案可能更惯用。就我个人而言,我更喜欢使用字母数字标签作为索引(而不是数字)以提高可读性(更容易记住每个按钮应该做什么),但是 YMMV。但是利用 $_POST['row'] 作为关联数组是聪明的!
我同意,如果您正在处理静态按钮,您应该使用命名键。但在某些情况下你不能。有时您会动态生成这些输入。最常见的情况是行列表,每行都由一个 id 标识。我想我在写答案时正在考虑那个案例(4年前!)。我已经对其进行了编辑,因此更明显的是该数字是 id 而不是索引。
做得好!是的,我同意,现在更明显了;我仍然相信您的答案比@Thielicious 的答案略好(甚至可能效率更高,尤其是在有很多按钮的情况下)。
t
tixastronauta

请注意,如果您有多个提交按钮并且您按回车键(ENTER 键),则键盘上的默认按钮值将是 DOM 上的第一个按钮。

例子:

<form>
  <input type="text" name="foo" value="bar">
  <button type="submit" name="operation" value="val-1">Operation #1</button>
  <button type="submit" name="operation" value="val-2">Operation #2</button>
</form>

如果您在此表单上按 ENTER,将发送以下参数:

foo=bar&operation=val-1

谢谢。这正是我想确认的。
J
Jonathan Laliberte

您还可以使用 href 属性并发送带有为每个按钮附加的值的 get。但是那时不需要表格

href="/SubmitForm?action=delete"
href="/SubmitForm?action=save"

这不适用于 POST 路由下的控制器。
因此,“发送获取”
很抱歉不同意,但 GET 并不总是合适的。如果您“修改模型的状态”,那么您不应使用 GET,因为刷新浏览器可能会导致透明地发送两次相同的请求。仅使用 GET 来“查看”事物,使用 POST 发送状态更改请求(添加、删除、编辑等)。然后在您的 POST 控制器操作中更改状态(数据库、会话...)并投射重定向响应,然后 GET 是新的更改状态。为模型状态更改执行 GET 非常肮脏,任何优秀的编码人员都应该避免这样做。很抱歉这么说。清洁代码规则。
真的。但是玩脏有时可以很干净。这取决于你在做什么。就个人而言,它不会在获取时映射删除和编辑请求,但有一些方法可以使它工作..比如检查它是否已经被删除,或者检查用户是否有权这样做等等......
R
Rohit Gupta

更新后的答案是使用带有 formaction 和 formtarget 的按钮

在此示例中,第一个按钮在新标签中启动不同的 URL /preview。其他三个使用 form 标记中指定的 action

<button type='submit' class='large' id='btnpreview' name='btnsubmit' value='Preview' formaction='/preview' formtarget='blank' >Preview</button>
<button type='submit' class='large' id='btnsave' name='btnsubmit' value='Save' >Save</button>
<button type='submit' class='large' id='btnreset' name='btnsubmit' value='Reset' >Reset</button>
<button type='submit' class='large' id='btncancel' name='btnsubmit' value='Cancel' >Cancel</button>

完整的documentation is here


N
Nikhil Gaur

在 HTML5 中,您可以使用 formaction & formmethod 输入字段中的属性

<form action="/addimage" method="POST">
<button>Add image</button>
<button formaction="/home" formmethod="get">Cancel</button>
<button formaction="/logout" formmethod="post">Logout</button>
</form>

S
Silvester

您可以像这样显示按钮:

<input type="submit" name="typeBtn" value="BUY">
<input type="submit" name="typeBtn" value="SELL">

然后在代码中,您可以使用以下方法获取值:

if request.method == 'POST':
    #valUnits = request.POST.get('unitsInput','')
    #valPrice = request.POST.get('priceInput','')
    valType = request.POST.get('typeBtn','')

(valUnits 和 valPrice 是我从留下的表格中提取的一些其他值,以供说明)


那是什么编程语言? Python
P
Pradip Kumar Raushan

由于您没有指定您使用的服务器端脚本方法,我将给您一个适用于 PHP 的示例

FORM-1 with 2 个按钮

Forms

When click on Login -> loginForm

When click on Save -> saveForm

When click on Register -> registrationForm


如果它实际上没有运行,为什么要把它放在片段中?语法突出显示已关闭。
P
Peter Mortensen

简单的。您可以更改表单对不同提交按钮单击的操作。

在文档中试试这个。准备好:

$(".acceptOffer").click(function () {
    $("form").attr("action", "/Managers/SubdomainTransactions");
});

$(".declineOffer").click(function () {
    $("form").attr("action", "/Sales/SubdomainTransactions");
});