ChatGPT解决这个技术问题 Extra ChatGPT

Two submit buttons in one form

I have two submit buttons in a form. How do I determine which one was hit serverside?

Consider changing the accepted answer to Parrots' answer.
@PeterMortensen - Neither the accepted answer nor Parrot's answer are the best today. See Leo's answer for the newer HTML5 solution using attribute formaction. Or see kiril's answer for how to have the HTML visible to user be independent of the value sent to browser - solving the internationalization problem in an easier-to-code way than either Greg's or Parrot's answer.

T
ToolmakerSteve

Solution 1: Give each input a different value and keep the same name:

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

Then in the code check to see which was triggered:

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

The problem with that is you tie your logic to the user-visible text within the input.

Solution 2: Give each one a unique name and check the $_POST for the existence of that input:

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

And in the code:

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

For i18n purposes it might be better to use the selected answer.
@LaszloPapp as the answer itself says, if you use the selected answer above, you can internationalize the form (i.e. translate into different languages or dialects) without affecting the logic. If you use the first option in this answer, the logic depends on the language the form is actually presented in.
@RobinGreen: I think most people will use the second logic, won't they?
i18n = i[nternationalizatio]n, and the 18 stands for the 18 letters between the first and the last.
The OP didn't ask for PHP.
G
Greg

If you give each one a name, the clicked one will be sent through as any other input.

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

Also make sure the name of the button has correct name! For example "button-1" would NOT work. May save someone lots of hassle so keep this in mind.
Normally, all inputs in the form are sent with the form. Since a button's value is submitted only if clicked, you'd have to search the form values for these pre-defined names. I think the other answer (stackoverflow.com/a/21778226/88409) that involves giving them all the same name, with different values, makes more sense. Then you just grab the value under a single known form field name. It also makes it more obvious that only one value (the clicked one) will be sent for the given input name, much like how radio buttons work (same name, different values).
@Triynko , as Robin Green said in the comments of that answer, this one is better for internationalization. For example, if the page is rendered in Spanish, the text of the buttons will likely be different. So having the logic of your code depend on the text of that button will break in that case. Going by the name is safer, as it is a value that is not displayed to the user and therefore can be treated more as a "private" variable and less as a message to users.
To clarify @sfarbota's comment: The first solution shown in Parrot's answer is problematic, as it relies on testing the user-visible value. That is dubious - code that breaks when changing a user-visible word is considered "fragile". The second solution shown in Parrot's answer is fine - it is the same as this one. Parrot's second solution also shows the corresponding code to write, hence it is a more useful answer than this one.
See Leo's answer for the newer HTML5 solution using attribute formaction. Or see kiril's answer for how to have the HTML visible to user be independent of the value sent to browser - solving the internationalization problem.
T
ToolmakerSteve

An even better solution consists of using button tags to submit the form:

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

The HTML inside the button (e.g. ..>Update<.. is what is seen by the user; because there is HTML provided, the value is not user-visible; it is only sent to server. This way there is no inconvenience with internationalization and multiple display languages (in the former solution, the label of the button is also the value sent to the server).


Apparently browser behaviour differs; some submit the value attribute, others the string between the tags ... So be careful with this one.
I think the snippet provided is fully supported (w3schools.com/tags/att_button_type.asp)
@kiril the snippet from that link uses two different types of <button>: submit and reset. Note that reset does not submit anything, it just resets the form. So Jeroen's argument remains.
Ok, your right. Then, I checked the HTML5 W3C Working Draft. Quoting: >>The value attribute gives the element's value for the purposes of form submission. The element's value is the value of the element's value attribute, if there is one, or the empty string otherwise. >>NOTE: A button (and its value) is only included in the form submission if the button itself was used to initiate the form submission.
@Jeroen Bull. Which browsers submit the text between the tags? An input or button should only ever submit the 'value' attribute. A button could literally have anything between it tags, including images or other HTML tags. That's the whole point of using a button over an input element, and you're trying to suggest the browser is going to dump all that content as the value? No way.
P
Peter Mortensen

There’s a new HTML5 approach to this, the formaction attribute:

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

Apparently this does not work in Internet Explorer 9 and earlier, but for other browsers you should be fine (see: w3schools.com HTML <button> formaction Attribute).

Personally, I generally use JavaScript to submit forms remotely (for faster perceived feedback) with this approach as backup. Between the two, the only people not covered are Internet Explorer before version 9 with JavaScript disabled.

Of course, this may be inappropriate if you’re basically taking the same action server-side regardless of which button was pushed, but often if there are two user-side actions available then they will map to two server-side actions as well.

As noted by Pascal_dher in the comments, this attribute is also available on the <input> tag as well.


Also available for "input" tag. Accoding to w3schools: when using button tag different browsers may submit different values: w3schools.com/tags/tag_button.asp
Note to Rails users: adding this attribute won't work if your form is created using form_tag. The only way I got it to work is to switch to form_for and use f.submit formaction: 'your_path'.
P
Peter Mortensen

This is extremely easy to test:

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

Just put that in an HTML page, click the buttons, and look at the URL.


Using GET here is a somewhat bad practice, one should be using POST when possible.
@Syncrossus That's for testing purposes.
P
Peter Mortensen

Use the formaction HTML attribute (5th line):

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

This is similar to Leo's earlier answer.
@ToolmakerSteve - But users have upvoted. take your pick!!
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 feature. Works perfectly on recent web browsers, thanks !
NOTE: This appears to be the same as Leo's earlier answer, except that it shows use of input tag rather than button tag.
P
Peter Mortensen

The best way to deal with multiple submit buttons is using a switch case in the server script

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

Server code/server script - where you are submitting the form:

File 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;
    }
?>

Source: W3Schools.com


yes it is you must have an idea about action scripts (server side scripting technology) You can use any script/file to process submitted data e.g. php, asp, jsp, etc. <form action="demo_form.php" method="get">
Okay. This was confusing because there is also a language named ActionScript. You should say: "server code" or "server script" instead.
I had no idea you could do that with buttons
submitting page usually uses method="POST"
There was an error, it says: : Undefined array key “subject” in C:\xampp\htdocs\Test-1\index.php
P
Peter Mortensen

Maybe the suggested solutions here worked in 2009, but I’ve tested all of this upvoted answers and nobody is working in any browsers.

The only solution I found working was this (but it's a bit ugly to use I think):

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

Why not just use formaction="actionurl1"? You don't need JavaScript.
@rybo111 IE9 browser (witch is relatively still used widely) does not support formaction
@inaliaghle True, its about 1% of users - it depends for whom the project is aimed at. Approx 1% of users don't use JavaScript.
For future readers: there's nothing wrong with using javascript, as in this answer. Its a useful skill to know. OTOH, the more highly upvoted answers also work fine - ignore the lead sentence of this answer. If for some reason you can't get those other answers to work, then post your complete code as an SO question, explain what happens (or doesn't happen), and ask what you are doing wrong.
P
Peter Mortensen

You formaction for multiple submit buttons in one form example:

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

This is incomprehensible. E.g., what do you mean by "You formaction"? Is a word missing? Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).
@PeterMortensen "formaction" stands for "form action", and it's an attribute that replaces the default form's action. If you do not declare a "formaction" for a submit button, the form will use its default route. If you do, it will use a specific route. You can read more here: w3schools.com/tags/att_input_formaction.asp
P
Peter Mortensen

An HTML example to send a different form action on different button clicks:

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

The same form is being used to add a new user and login user.


never thought this was there
P
Peter Mortensen

Define name as 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>

Example server code (PHP):

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

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

elseif very important, because both will be parsed if not.


Now this is an excellent suggestion — mostly because you can add more buttons with more cases very easily, and use a switch with a default action if one has added a button and forgotten to add it to the switch (and/or misspelt something etc.)
Also, @Pato added a similar answer which is possibly more idiomatic, but yours works fine!
@GwynethLlewelyn I didn't see the other answer back or did not notice when I wrote my own. It's actually the same, but this simply emphasizes how most people prefer this logic. Difference is just with names for semantic reasons, good understanding for rookies or whoever likes to start with it.
Will this pass HTML validation? E.g. without quotes?
Re "Define name as array": Can you elaborate, including links to official documentation about this array thingy/convention/syntax (specific to PHP?)? (But without "Edit:", "Update:", or similar - the answer should appear as if it was written today.)
P
Peter Mortensen

Since you didn't specify what server-side scripting method you're using, I'll give you an example that works for Python, using CherryPy (although it may be useful for other contexts, too):

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

Rather than using the value to determine which button was pressed, you can use the name (with the <button> tag instead of <input>). That way, if your buttons happen to have the same text, it won't cause problems. The names of all form items, including buttons, are sent as part of the URL.

In CherryPy, each of those is an argument for a method that does the server-side code. So, if your method just has **kwargs for its parameter list (instead of tediously typing out every single name of each form item) then you can check to see which button was pressed like this:

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>

What is this? PHP? This doesn't look like valid PHP. Is it heredoc? In any case, an explanation would be in order. E.g., what is the idea/gist? Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).
P
Peter Mortensen

I think you should be able to read the name/value in your GET array. I think that the button that wasn't clicked won't appear in that list.


You most probably mean the POST array.
Not necessarily, if the form's method is "POST" it won't show up in the GET array. Most forms are submitted via POST.
Either/or is technically right, and yet so wrong. You can submit a form with method="GET", but it is cringeworthy.
It is only "cringeworthy" when used inappropriately: w3.org/2001/tag/doc/whenToUseGet.html.
Yeah I wasn't trying to suggest GET, I was just trying to generalize things.
P
Peter Mortensen

You can also do it like this (I think it's very convenient if you have N inputs).

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

A common use case would be using different ids from a database for each button, so you could later know in the server which row was clicked.

In the server side (PHP in this example) you can read "row" as an array to get the id.

$_POST['row'] will be an array with just one element, in the form [ id => value ] (for example: [ '123' => 'something' ]).

So, in order to get the clicked id, you do:

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

key


This is similar to the answer @Thielicious posted, but yours is possibly more idiomatic. Personally I prefer using alphanumeric tags for the index (as opposed to numbers) for readability (easier to remember what each button is supposed to do), but YMMV. But taking advantage of $_POST['row'] being an associative array is clever!
I agree that, if you are dealing with static buttons, you should use named keys. But in some cases you can't. Sometimes you generate those inputs dynamically. The most common case of this would be a list of rows, each one identified by an id. I guess I was thinking about that case when I wrote the answer (4 years ago!). I've edited it so it is more obvious that the number is an id and not an index.
Well done! Aye, I agree, it's more obvious now; I still believe that your answer is marginally better than the one by @Thielicious (and possibly even a bit more efficient, especially if there are many buttons).
t
tixastronauta

As a note, if you have multiple submit buttons and you hit return (ENTER key), on the keyboard the default button value would be of the first button on the DOM.

Example:

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

If you hit ENTER on this form, the following parameters will be sent:

foo=bar&operation=val-1

Thanks. This is exactly what I wanted to confirm.
J
Jonathan Laliberte

You can also use a href attribute and send a get with the value appended for each button. But the form wouldn't be required then

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

This would not work for controllers under POST routes.
hence, "send a get"
I'm sorry to disagree, but GET is not always suitable. If you "modify the state of your model" then you should never use a GET, as refreshing the browser could yield in transparently sending two times the same request. Use GET only to "view" things and POST to send requests of state changes (add, remove, edit, etc.). then in your POST controller action alter the state (database, sesion...) and cast a redirect-response that then GETs the new altered state. Doing GET for model-state-alteration is very dirty and any good coder should avoid so. Sorry to say that. Clean code rulez.
True. But playing dirty can sometimes be clean. It depends on what you are doing exactly. Personally it would not map delete and edit requests on a get, but there are ways to make it work.. like checking if it has already been deleted, or checking if the user has permission to do so etc...
R
Rohit Gupta

The updated answer is to use the button with formaction and formtarget

In this example, the first button launches a different url /preview in a new tab. The other three use the action specified in the form tag.

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

Full documentation is here


N
Nikhil Gaur

In HTML5, you can use formaction & formmethod attributes in the input field

<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

You can present the buttons like this:

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

And then in the code you can get the value using:

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

(valUnits and valPrice are some other values I extract from the form that I left in for illustration)


What programming language is that? Python?
P
Pradip Kumar Raushan

Since you didn't specify what server-side scripting method you're using, I'll give you an example that works for PHP

FORM-1 with 2 buttons
FORM-2 with 1 button

Forms

When click on Login -> loginForm

When click on Save -> saveForm

When click on Register -> registrationForm


Why put it in snippets if it doesn't actually run? The syntax highlighting is off.
P
Peter Mortensen

Simple. You can change the action of form on different submit buttons click.

Try this in document.Ready:

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

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