Dos botones de envío en una forma

534

Tengo dos botones de envío en un formulario. ¿Cómo determino cuál fue golpeado en el servidor?

Alex
fuente
Considere cambiar la respuesta aceptada a la respuesta de Parrots .
Peter Mortensen
2
@PeterMortensen - Ni la respuesta aceptada ni la respuesta de Parrot son las mejores hoy. Vea la respuesta de Leo para la nueva solución HTML5 usando el atributo formaction. O vea la respuesta de kiril sobre cómo hacer que el HTML sea visible para el usuario sea independiente del valor enviado al navegador, resolviendo el problema de internacionalización de una manera más fácil de codificar que la respuesta de Greg o Parrot.
ToolmakerSteve

Respuestas:

448

Si le da un nombre a cada uno, el clic será enviado como cualquier otra entrada.

<input type="submit" name="button_1" value="Click me">
Greg
fuente
101
¡También asegúrese de que el nombre del botón tenga el nombre correcto! Por ejemplo, "botón-1" NO funcionaría. Puede ahorrarle problemas a alguien, así que tenga esto en cuenta.
pdolinaj
22
Normalmente, todas las entradas en el formulario se envían con el formulario. Dado que el valor de un botón se envía solo si se hace clic, tendría que buscar en los valores del formulario estos nombres predefinidos. Creo que la otra respuesta ( stackoverflow.com/a/21778226/88409 ) que implica darles a todos el mismo nombre, con valores diferentes, tiene más sentido. Luego simplemente toma el valor bajo un solo nombre de campo de formulario conocido. También hace que sea más obvio que solo se enviará un valor (el clic) para el nombre de entrada dado, de forma muy similar a cómo funcionan los botones de opción (mismo nombre, valores diferentes).
Triynko
66
@Triynko, como Robin Green dijo en los comentarios de esa respuesta, esta es mejor para la internacionalización. Por ejemplo, si la página se representa en español, el texto de los botones probablemente será diferente. Entonces, tener la lógica de su código depende del texto de ese botón se romperá en ese caso. Ir por el nombre es más seguro, ya que es un valor que no se muestra al usuario y, por lo tanto, puede tratarse más como una variable "privada" y menos como un mensaje para los usuarios.
sfarbota
Para aclarar el comentario de @ sfarbota: La primera solución que se muestra en la respuesta de Parrot es problemática, ya que se basa en probar el valor visible para el usuario . Eso es dudoso: el código que se rompe al cambiar una palabra visible para el usuario se considera "frágil". La segunda solución que se muestra en la respuesta de Parrot está bien, es la misma que esta. La segunda solución de Parrot también muestra el código correspondiente para escribir, por lo tanto, es una respuesta más útil que esta.
ToolmakerSteve
2
Vea la respuesta de Leo para la nueva solución HTML5 usando el atributo formaction. O vea la respuesta de kiril sobre cómo hacer que el HTML sea visible para el usuario sea independiente del valor enviado al navegador, resolviendo el problema de internacionalización.
ToolmakerSteve
875

Solución 1:
asigne a cada entrada un valor diferente y mantenga el mismo nombre:

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

Luego, en el código, verifique qué se activó:

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

El problema con eso es que vincula su lógica al texto visible para el usuario dentro de la entrada.


Solución 2:
asigne a cada uno un nombre único y compruebe $ _POST para ver si existe esa entrada:

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

Y en el código:

if (isset($_POST['update_button'])) {
    //update action
} else if (isset($_POST['delete_button'])) {
    //delete action
} else {
    //no button pressed
}
Loros
fuente
37
Para fines de 1818 podría ser mejor usar la respuesta seleccionada.
Robin Green
11
@LaszloPapp como dice la respuesta, si usa la respuesta seleccionada arriba, puede internacionalizar el formulario (es decir, traducirlo a diferentes idiomas o dialectos) sin afectar la lógica. Si utiliza la primera opción en esta respuesta, la lógica depende del idioma en el que se presenta el formulario.
Robin Green
1
@RobinGreen: Creo que la mayoría de la gente usará la segunda lógica, ¿no?
lpapp
55
i18n = i [nternationalizatio] n, y el 18 representa las 18 letras entre la primera y la última.
Buttle Butkus
18
El OP no solicitó PHP.
Rudey
110

Una solución aún mejor consiste en usar etiquetas de botón para enviar el formulario:

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

El HTML dentro del botón (por ejemplo, ..>Update<..es lo que ve el usuario; porque se proporciona HTML, valueno es visible para el usuario; solo se envía al servidor. De esta manera no hay inconveniente con la internacionalización y los múltiples idiomas de visualización (en el antigua solución, la etiqueta del botón también es el valor enviado al servidor).

Kiril
fuente
13
Aparentemente, el comportamiento del navegador difiere; algunos envían el atributo de valor, otros la cadena entre las etiquetas ... Así que tenga cuidado con este.
Jeroen Dierckx
1
Creo que el fragmento proporcionado es totalmente compatible ( w3schools.com/tags/att_button_type.asp )
kiril
2
@kiril el fragmento de ese enlace utiliza dos tipos diferentes de <button>: submity reset. Tenga en cuenta que resetno envía nada, solo restablece el formulario. Entonces el argumento de Jeroen permanece.
fizruk
77
Ok, tienes razón. Luego, revisé el Borrador de Trabajo HTML5 W3C. Cita: >> El atributo de valor proporciona el valor del elemento a los efectos del envío del formulario. El valor del elemento es el valor del atributo de valor del elemento, si hay uno, o la cadena vacía de lo contrario. >> NOTA: Un botón (y su valor) solo se incluye en el envío del formulario si el botón mismo se usó para iniciar el envío del formulario.
Kiril
8
@Jeroen Bull. ¿Qué navegadores envían el texto entre las etiquetas? Una entrada o botón solo debe enviar el atributo 'valor'. Un botón podría tener literalmente cualquier cosa entre sus etiquetas, incluidas imágenes u otras etiquetas HTML. Ese es el objetivo de usar un botón sobre un elemento de entrada, y ¿estás tratando de sugerir que el navegador va a volcar todo ese contenido como valor? De ninguna manera.
Triynko
93

Hay un nuevo enfoque HTML5 para esto, el formactionatributo:

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

Aparentemente, esto no funciona en IE9 y versiones anteriores, pero para otros navegadores debería estar bien (vea: w3schools.com HTML <button> formaction Attribute ).

Personalmente, generalmente uso Javascript para enviar formularios de forma remota (para una retroalimentación percibida más rápida) con este enfoque como copia de seguridad. Entre los dos, las únicas personas que no están cubiertas son IE <9 con Javascript deshabilitado.

Por supuesto, esto puede ser inapropiado si básicamente está tomando la misma acción del lado del servidor, independientemente de qué botón se haya presionado, pero a menudo si hay dos acciones del lado del usuario disponibles, también se asignarán a dos acciones del lado del servidor.

Editar: como señaló Pascal_dher en los comentarios, este atributo también está disponible en la <input>etiqueta.

León
fuente
1
También disponible para la etiqueta "input". De acuerdo con w3schools: cuando se usa la etiqueta de botón, diferentes navegadores pueden enviar diferentes valores: w3schools.com/tags/tag_button.asp
Pascal_dher
3
He sido desarrollador web durante 12 años y este es nuevo para mí y en realidad era exactamente lo que necesitaba. ¡Gracias!
KyleFarris
1
De nada @KyleFarris! Creo que esto solo ha sido posible hace relativamente poco tiempo, por lo que no es de extrañar que aún no lo hayas encontrado.
Leo
2
Nota para los usuarios de Rails: agregar este atributo no funcionará si su formulario se crea usando form_tag. La única forma de hacerlo funcionar es cambiar form_fory usar f.submit formaction: 'your_path'.
fgblomqvist
2
formactionen MDN
akinuri
27

Esto es extremadamente fácil de probar

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

Simplemente colóquelo en una página HTML, haga clic en los botones y mire la URL

Peter Bailey
fuente
55
Usar GET aquí es una práctica algo mala, uno debería usar POST cuando sea posible.
Syncrossus
66
@Syncrossus Eso es para fines de prueba.
Etienne Martin
22

Use el formactionatributo HTML (5ª línea):

<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>
Thirumalmani Lavanyan
fuente
2
Esto es similar a la respuesta anterior de Leo .
ToolmakerSteve
@ToolmakerSteve - Pero los usuarios han votado positivamente . ¡¡elige tu opción!!
user12379095
21
<form>
    <input type="submit" value="Submit to a" formaction="/submit/a">
    <input type="submit" value="submit to b" formaction="/submit/b">    
</form>
MevlütÖzdemir
fuente
Característica HTML5. Funciona perfectamente en navegadores web recientes, ¡gracias!
Stephane Lallemagne
1
NOTA: Esto parece ser lo mismo que la respuesta anterior de Leo , excepto que muestra el uso de la inputetiqueta en lugar de la buttonetiqueta.
ToolmakerSteve
11

La mejor manera de lidiar con el botón de envío múltiple es mediante el uso de mayúsculas y minúsculas en la secuencia de comandos del servidor

<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">Java Script</button>
<button name="subject" type="submit" value="jquery">jQuery</button>

</form>

código del servidor / secuencia de comandos del servidor - donde está enviando el formulario:

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

?>

Fuente: W3Schools.com

Shailesh Sonare
fuente
Sí, debe tener una idea sobre los scripts de acción (tecnología de scripts del lado del servidor). Puede usar cualquier script / archivo para procesar los datos enviados, por ejemplo, php, asp, jsp, etc. <form action="demo_form.php" method="get">
Shailesh Sonare
Bueno. Esto fue confuso porque también hay un lenguaje llamado ActionScript. Debería decir: "código de servidor" o "script de servidor" en su lugar.
Civil
No tenía idea de que podías hacer eso con botones
William Isted
10

Quizás las soluciones sugeridas aquí funcionaron en 2009, pero he probado todas estas respuestas votadas y nadie está trabajando en ningún navegador.

La única solución que encontré que funciona es esta: (pero creo que es un poco feo de usar)

<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';"/>

Joakim
fuente
2
¿Por qué no solo usar formaction="actionurl1"? No necesitas JavaScript.
rybo111
3
@ rybo111 IE9 browser (la bruja es relativamente utilizada todavía) no es compatibleformaction
clueless007
1
@inaliaghle Es cierto, es aproximadamente el 1% de los usuarios, depende de a quién va dirigido el proyecto. Aproximadamente el 1% de los usuarios no usan JavaScript.
rybo111
1
Para futuros lectores: no hay nada de malo en usar JavaScript, como en esta respuesta. Es una habilidad útil para saber. OTOH, las respuestas más votadas también funcionan bien: ignore la oración principal de esta respuesta. Si por alguna razón no puede hacer que esas otras respuestas funcionen, publique su código completo como una pregunta SO, explique qué sucede (o no sucede) y pregunte qué está haciendo mal.
ToolmakerSteve
6

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

Ejemplo de código de servidor (PHP):

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

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

elseifmuy importante, porque ambos se analizarán si no. Disfrutar.

Thielicious
fuente
Ahora, esta es una excelente sugerencia, principalmente porque puede agregar más botones con más casos muy fácilmente, y usar un switchcon una acción predeterminada si uno ha agregado un botón y se olvidó de agregarlo a switch(y / o escribir mal algo, etc.)
Gwyneth Llewelyn
Además, @Pato agregó una respuesta similar que posiblemente sea más idiomática, ¡pero la tuya funciona bien!
Gwyneth Llewelyn
1
@GwynethLlewelyn No vi la otra respuesta o no me di cuenta cuando escribí la mía. En realidad es lo mismo, pero esto simplemente enfatiza cómo la mayoría de la gente prefiere esta lógica. La diferencia es solo con los nombres por razones semánticas, una buena comprensión para los novatos o para quienes les gusta comenzar con ellos.
Thielicious
5

Como no especificó qué método de script del lado del servidor está utilizando, le daré un ejemplo que funciona para Python, usando CherryPy (aunque también puede ser útil para otros contextos):

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

En lugar de usar el valor para determinar qué botón se presionó, puede usar el nombre (con la <button>etiqueta en lugar de <input>). De esa forma, si sus botones tienen el mismo texto, no causará problemas. Los nombres de todos los elementos del formulario, incluidos los botones, se envían como parte de la URL. En CherryPy, cada uno de ellos es un argumento para un método que hace el código del lado del servidor. Entonces, si su método solo tiene **kwargssu lista de parámetros (en lugar de escribir tediosamente cada nombre de cada elemento del formulario), puede verificar qué botón se presionó de esta manera:

if "register" in kwargs:
    pass #Do the register code
elif "login" in kwargs:
    pass #Do the login code
Brōtsyorfuzthrāx
fuente
3
<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>
Osmar Kozan Jr
fuente
2

Creo que debería poder leer el nombre / valor en su matriz GET. Creo que el botón en el que no se hizo clic no aparecerá en esa lista.

John Bubriski
fuente
Probablemente te refieres a la matriz POST.
ypnos
3
No necesariamente, si el método del formulario es "POST", no aparecerá en la matriz GET. La mayoría de los formularios se envían a través de POST.
Loros
2
Cualquiera de los dos es técnicamente correcto y, sin embargo, tan incorrecto. Puede enviar un formulario con method = "GET", pero es cringeworthy.
Bill the Lizard
44
Solo es "cringeworthy" cuando se usa de manera inapropiada: w3.org/2001/tag/doc/whenToUseGet.html .
mercator
2
Sí, no estaba tratando de sugerir GET, solo estaba tratando de generalizar las cosas.
John Bubriski
1

También puede hacerlo así (creo que es muy conveniente si tiene N entradas).

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

Un caso de uso común sería usar diferentes identificadores de una base de datos para cada botón, para que luego pueda saber en el servidor en qué fila se hizo clic.

En el lado del servidor (PHP en este ejemplo) puede leer "fila" como una matriz para obtener la identificación. $_POST['row']será una matriz con solo un elemento, en la forma [ id => value ](por ejemplo:) [ '123' => 'something' ].

Entonces, para obtener la identificación clicada, debes:

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

http://php.net/manual/en/function.key.php

Pato
fuente
Esto es similar a la respuesta publicada por @Thielicious , pero la suya es posiblemente más idiomática. Personalmente, prefiero usar etiquetas alfanuméricas para el índice (en lugar de números) para facilitar la lectura (es más fácil recordar lo que se supone que debe hacer cada botón), pero YMMV. ¡Pero aprovechar $_POST['row']ser una matriz asociativa es inteligente!
Gwyneth Llewelyn
1
Estoy de acuerdo en que, si se trata de botones estáticos, debe usar teclas con nombre. Pero en algunos casos no puedes. A veces genera esas entradas dinámicamente. El caso más común de esto sería una lista de filas, cada una identificada por una identificación. Creo que estaba pensando en ese caso cuando escribí la respuesta (¡hace 4 años!). Lo he editado, por lo que es más obvio que el número es una identificación y no un índice.
Pato
¡Bien hecho! Sí, estoy de acuerdo, es más obvio ahora; Todavía creo que su respuesta es marginalmente mejor que la de @Thielicious (y posiblemente incluso un poco más eficiente, especialmente si hay muchos botones).
Gwyneth Llewelyn
1

Tu formación para botón de envío múltiple en un ejemplo de formulario

 <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"> 
thirumal mani L
fuente
0

Simple puede cambiar la acción del formulario en diferentes botones de enviar Haga clic.

Pruebe esto en el documento.

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

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

También puede usar un atributo href y enviar un get con el valor agregado para cada botón. Pero el formulario no sería requerido entonces

href="/SubmitForm?action=delete"
href="/SubmitForm?action=save"
Jonathan Laliberte
fuente
Esto no funcionaría para controladores bajo POSTrutas.
Xavi Montero
por lo tanto, "envíe un mensaje"
Jonathan Laliberte
3
Lamento no estar de acuerdo, pero GETno siempre es adecuado. Si "modifica el estado de su modelo" , nunca debería usar a GET, ya que la actualización del navegador podría generar el envío transparente de dos veces la misma solicitud. Úselo GETsolo para "ver" cosas y POSTenviar solicitudes de cambios de estado (agregar, eliminar, editar, etc.). luego, en la POSTacción del controlador, altere el estado (base de datos, sesion ...) y emita una respuesta de redireccionamiento que luego sea GETel nuevo estado alterado. Hacer la GETalteración del estado del modelo es muy sucio y cualquier buen codificador debería evitarlo. Lamento decir eso. Código limpio rulez.
Xavi Montero
Cierto. Pero jugar sucio a veces puede ser limpio. Depende de lo que estés haciendo exactamente. Personalmente, no mapearía las solicitudes de eliminación y edición en un get, pero hay formas de hacerlo funcionar ... como verificar si ya se ha eliminado, o verificar si el usuario tiene permiso para hacerlo, etc ...
Jonathan Laliberte
-1

Puede presentar los botones de esta manera:

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

Y luego, en el código, puede obtener el valor usando:

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

(valUnits y valPrice son algunos otros valores que extraigo del formulario que dejé como ilustración)

usuario3714578
fuente
-1

Como no especificó qué método de script del lado del servidor está utilizando, le daré un ejemplo que funciona para 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>

Formas

Cuando haga clic en Iniciar sesión -> loginForm

Cuando haga clic en Guardar -> saveForm

Cuando haga clic en Registrarse -> RegistrationForm

Pradip Kumar Raushan
fuente