【问题标题】:Two submit buttons in one form一个表单中的两个提交按钮
【发布时间】:2010-10-07 13:31:35
【问题描述】:

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

【问题讨论】:

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

标签: html forms submit


【解决方案1】:

请注意,如果您有多个提交按钮并按下回车键(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

【讨论】:

    【解决方案2】:

    一个在不同按钮点击时发送不同表单动作的 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>
    

    正在使用相同的表单添加新用户和登录用户。

    【讨论】:

    • 没想到这里有
    【解决方案3】:

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

     <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 回复,而不是在 cmets 中(without "Edit:"、"Update:" 或类似的 - 答案应该看起来像是今天写的)。
    • @PeterMortensen "formaction" 代表“表单动作”,它是一个替换默认表单动作的属性。如果您没有为提交按钮声明“formaction”,则表单将使用其默认路由。如果你这样做,它将使用特定的路线。你可以在这里阅读更多:w3schools.com/tags/att_input_formaction.asp
    【解决方案4】:

    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 和默认操作switch(和/或拼写错误的东西等)
    • 另外,@Pato 添加了 similar answer,这可能更惯用,但你的工作正常!
    • @GwynethLlewelyn 我没有看到其他答案,或者我写自己的答案时没有注意到。它实际上是相同的,但这只是强调大多数人更喜欢这种逻辑。区别只是出于语义原因的名称,对于新手或喜欢从它开始的人来说很好理解。
    • 这会通过 HTML 验证吗?例如。没有引号?
    • Re "Define name as array":您能详细说明一下,包括有关此数组thingy/convention/syntax(特定于PHP?)的官方文档的链接吗? (但没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的。)
    【解决方案5】:

    处理多个提交按钮的最佳方法是在服务器脚本中使用 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等&lt;form action="demo_form.php" method="get"&gt;
    • 好的。这很令人困惑,因为还有一种名为 ActionScript 的语言。你应该说:“服务器代码”或“服务器脚本”。
    • 我不知道你可以用按钮做到这一点
    • 提交页面通常使用method="POST"
    • 出现错误,提示:C:\xampp\htdocs\Test-1\index.php 中未定义的数组键“subject”
    【解决方案6】:
    <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 回复,而不是在 cmets 中(without "Edit:"、"Update:" 或类似的 - 答案应该看起来像是今天写的)。
    【解决方案7】:

    你也可以这样(我觉得有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 =&gt; value ](例如:[ '123' =&gt; 'something' ])。

    所以,为了获得点击的 id,你需要这样做:

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

    key

    【讨论】:

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

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

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

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

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

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

    【讨论】:

      【解决方案9】:

      有一种新的 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 远程提交表单(以获得更快的感知反馈),并将这种方法作为备份。在这两者之间,唯一未涵盖的人是 I​​nternet Explorer 版本 9 之前禁用了 JavaScript。

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

      正如 Pascal_dher 在 cmets 中所指出的,此属性也可用于 &lt;input&gt; 标记。

      【讨论】:

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

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

      document.Ready中试试这个:

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

      【讨论】:

        【解决方案11】:

        也许这里建议的解决方案在 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 问题发布,解释发生了什么(或没有发生),并询问您做错了什么。
        【解决方案12】:

        这非常容易测试:

        <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 用于测试目的。
        【解决方案13】:

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

        【讨论】:

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

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

        <?php
           if(isset($_POST["loginForm"]))
           {
            print_r ($_POST); // FOR Showing POST DATA
           }
           elseif(isset($_POST["registrationForm"]))
           {
            print_r ($_POST);
           }
           elseif(isset($_POST["saveForm"]))
           {
            print_r ($_POST);
           }
           else{
        
           }
        ?>
        <html>
        <head>
        </head>
        <body>
          
          <fieldset>
            <legend>FORM-1 with 2 buttons</legend>
              <form method="post" >
              <input type="text" name="loginname" value ="ABC" >
        
             <!--Always use type="password" for password --> 
             <input type="text" name="loginpassword" value ="abc123" >
             
             <input type="submit" name="loginForm" value="Login"><!--SUBMIT Button 1 -->
             <input type="submit" name="saveForm" value="Save">  <!--SUBMIT Button 2 -->
           </form>
          </fieldset>
        
        
        
          <fieldset>
            <legend>FORM-2 with 1 button</legend>
             <form method="post" >
              <input type="text" name="registrationname" value ="XYZ" >
              
             <!--Always use type="password" for password -->
             <input type="text" name="registrationpassword" value ="xyz123" >
             
             <input type="submit" name="registrationForm" value="Register"> <!--SUBMIT Button 3 -->
           </form>
          </fieldset>
          
        
        </body>
        </html>

        Forms

        When click on Login -> loginForm

        When click on Save -> saveForm

        When click on Register -> registrationForm

        【讨论】:

        • 如果它实际上没有运行,为什么要把它放在sn-ps中?语法高亮已关闭。
        【解决方案15】:

        更好的解决方案是使用按钮标签提交表单:

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

        内部按钮的HTML(例如..&gt;Update&lt;..是用户看到的;因为提供了HTML,value是用户不可见的;它只发送到服务器. 这样就没有国际化和多种显示语言的不便(前一种方案,按钮的标签也是发给服务器的值)。

        【讨论】:

        • 显然浏览器行为不同;有些提交 value 属性,有些提交标签之间的字符串......所以要小心这个。
        • 我认为提供的sn-p是完全支持的(w3schools.com/tags/att_button_type.asp)
        • @kiril 来自该链接的 sn-p 使用两种不同类型的 &lt;button&gt;submitreset。请注意,reset 不提交任何内容,它只是重置表单。所以 Jeroen 的论点仍然存在。
        • 好的,你说得对。然后,我查看了 HTML5 W3C 工作草案。引用: >>value 属性为表单提交提供元素的值。元素的值是元素的 value 属性的值,如果有,则为空字符串,否则为空字符串。 >>注意:仅当按钮本身用于启动表单提交时,按钮(及其值)才会包含在表单提交中。
        • @Jeroen Bull。哪些浏览器提交标签之间的文本?输入或按钮只应提交“值”属性。一个按钮实际上可以在它的标签之间有任何东西,包括图像或其他 HTML 标签。这就是在输入元素上使用按钮的全部意义,并且您试图建议浏览器将所有这些内容作为值转储?没办法。
        【解决方案16】:

        解决方案 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[nternationalizatio]n,18代表第一个和最后一个之间的18个字母。
        • OP 没有要求 PHP。
        【解决方案17】:

        使用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>
        

        【讨论】:

        【解决方案18】:

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

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

        【讨论】:

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

        你可以像这样展示按钮:

        <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?
        【解决方案21】:

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

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

        【讨论】:

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