Dwa przyciski przesyłania w jednej formie

534

Mam dwa przyciski przesyłania w formularzu. Jak ustalić, który z nich trafił na serwer?

Alex
źródło
Rozważ zmianę zaakceptowanej odpowiedzi na odpowiedź Papugi .
Peter Mortensen
2
@PeterMortensen - Ani zaakceptowana odpowiedź, ani odpowiedź Parrot nie są dziś najlepsze. Zobacz odpowiedź Leo na nowsze rozwiązanie HTML5 korzystające z atrybutu formaction. Lub zobacz odpowiedź Kirila, w jaki sposób HTML powinien być widoczny dla użytkownika, aby był niezależny od wartości wysyłanej do przeglądarki - rozwiązując problem internacjonalizacji w sposób łatwiejszy do zakodowania niż odpowiedź Grega lub Parrot.
ToolmakerSteve

Odpowiedzi:

446

Jeśli nadasz każdemu nazwę, kliknięty zostanie wysłany jak każde inne wejście.

<input type="submit" name="button_1" value="Click me">
Greg
źródło
101
Upewnij się także, że nazwa przycisku ma poprawną nazwę! Na przykład „przycisk-1” NIE działałby. Może zaoszczędzić komuś wiele kłopotów, więc miej to na uwadze.
pdolinaj
22
Zwykle wszystkie dane wejściowe w formularzu są wysyłane wraz z formularzem. Ponieważ wartość przycisku jest przesyłana tylko po kliknięciu, należy przeszukać wartości formularza w celu uzyskania wstępnie zdefiniowanych nazw. Myślę, że inna odpowiedź ( stackoverflow.com/a/21778226/88409 ), która polega na nadaniu im wszystkich tych samych nazw i różnych wartości, ma większy sens. Następnie wystarczy pobrać wartość pod jedną znaną nazwą pola formularza. Sprawia również, że bardziej oczywiste jest, że dla podanej nazwy wejściowej zostanie wysłana tylko jedna wartość (kliknięta), podobnie jak działają przyciski opcji (ta sama nazwa, różne wartości).
Triynko,
6
@Triynko, jak powiedział Robin Green w komentarzach do tej odpowiedzi, ta jest lepsza do internacjonalizacji. Na przykład, jeśli strona jest renderowana w języku hiszpańskim, tekst przycisków będzie prawdopodobnie inny. Tak więc logika twojego kodu zależy od tekstu tego przycisku, w takim przypadku psuje się. Posługiwanie się nazwą jest bezpieczniejsze, ponieważ jest to wartość, która nie jest wyświetlana użytkownikowi, a zatem może być traktowana bardziej jako zmienna „prywatna”, a mniej jako wiadomość dla użytkowników.
sfarbota,
Aby wyjaśnić komentarz @ sfarbota: Pierwsze rozwiązanie przedstawione w odpowiedzi Parrot jest problematyczne, ponieważ polega na przetestowaniu wartości widocznej dla użytkownika . Jest to wątpliwe - kod, który pęka przy zmianie słowa widocznego dla użytkownika, jest uważany za „delikatny”. Drugie rozwiązanie przedstawione w odpowiedzi Parrot jest w porządku - to jest taki sam jak ten. Drugie rozwiązanie Parrot pokazuje również odpowiedni kod do napisania, dlatego jest to bardziej użyteczna odpowiedź niż ta.
ToolmakerSteve
2
Zobacz odpowiedź Leo na nowsze rozwiązanie HTML5 korzystające z atrybutu formaction. Lub zobacz odpowiedź Kirila, w jaki sposób HTML powinien być widoczny dla użytkownika, aby był niezależny od wartości wysyłanej do przeglądarki - rozwiązując problem internacjonalizacji.
ToolmakerSteve
875

Rozwiązanie 1:
Nadaj każdemu wejściowi inną wartość i zachowaj tę samą nazwę:

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

Następnie w kodzie sprawdź, który został uruchomiony:

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

Problem polega na tym, że wiążesz swoją logikę z tekstem widocznym dla użytkownika w danych wejściowych.


Rozwiązanie 2:
Nadaj każdemu unikalną nazwę i sprawdź $ _POST pod kątem istnienia tych danych wejściowych:

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

I w kodzie:

if (isset($_POST['update_button'])) {
    //update action
} else if (isset($_POST['delete_button'])) {
    //delete action
} else {
    //no button pressed
}
Papugi
źródło
37
Dla celów i18n może być lepiej użyć wybranej odpowiedzi.
Robin Green,
11
@LaszloPapp, jak sama odpowiedź mówi, jeśli użyjesz wybranej powyżej odpowiedzi, możesz umiędzynarodowić formularz (tj. Przetłumaczyć na różne języki lub dialekty) bez wpływu na logikę. Jeśli użyjesz pierwszej opcji w tej odpowiedzi, logika zależy od języka, w którym formularz jest faktycznie prezentowany.
Robin Green,
1
@RobinGreen: Myślę, że większość ludzi będzie używać drugiej logiki, prawda?
lpapp,
5
i18n = i [nternationalizatio] n, a 18 oznacza 18 liter między pierwszą a ostatnią.
Buttle Butkus,
18
OP nie poprosił o PHP.
Rudey,
110

Jeszcze lepsze rozwiązanie polega na użyciu tagów przycisków do przesłania formularza:

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

HTML wewnątrz przycisku (np. ..>Update<..To, co widzi użytkownik; ponieważ dostępny jest HTML, valuenie jest widoczny dla użytkownika; jest wysyłany tylko na serwer. W ten sposób nie ma żadnych niedogodności związanych z internacjonalizacją i wieloma językami wyświetlania (w poprzednie rozwiązanie, etykieta przycisku jest również wartością wysyłaną do serwera).

kiril
źródło
13
Najwyraźniej zachowanie przeglądarki jest inne; niektórzy przesyłają atrybut wartości, inni ciąg między tagami ... Więc bądź ostrożny z tym.
Jeroen Dierckx
1
Myślę, że udostępniony fragment jest w pełni obsługiwany ( w3schools.com/tags/att_button_type.asp )
kiril
2
@kiril fragment tego linku używa dwóch różnych typów <button>: submiti reset. Pamiętaj, że resetnic nie przesyła, tylko resetuje formularz. Tak więc argument Jeroena pozostaje.
fizruk
7
Ok, masz rację. Następnie sprawdziłem roboczą wersję roboczą HTML5 W3C. Cytując: >> Atrybut wartości podaje wartość elementu na potrzeby przesłania formularza. Wartość elementu jest wartością atrybutu wartości elementu, jeśli istnieje, lub pustym łańcuchem w innym przypadku. >> UWAGA: Przycisk (i jego wartość) jest uwzględniany przy wysyłaniu formularza tylko wtedy, gdy sam przycisk został użyty do zainicjowania złożenia formularza.
kiril
8
@Jeroen Bull. Które przeglądarki przesyłają tekst między tagami? Dane wejściowe lub przycisk powinny zawsze przesyłać tylko atrybut „wartość”. Przycisk może dosłownie mieć wszystko między znacznikami, w tym obrazy lub inne znaczniki HTML. Taki jest sens używania przycisku nad elementem wejściowym, a próbujesz zasugerować, że przeglądarka zrzuci całą tę zawartość jako wartość? Nie ma mowy.
Triynko,
93

Jest do tego nowe podejście HTML5, formactionatrybut:

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

Najwyraźniej nie działa to w IE9 i wcześniejszych wersjach , ale w przypadku innych przeglądarek powinno być w porządku (patrz: w3schools.com HTML <button> formaction Attribute ).

Osobiście zazwyczaj używam Javascript do zdalnego przesyłania formularzy (w celu szybszego odbierania opinii), stosując to podejście jako kopię zapasową. Między nimi jedynymi osobami, których nie obejmuje, jest IE <9 z wyłączonym Javascript.

Oczywiście może to być nieodpowiednie, jeśli w zasadzie podejmujesz tę samą akcję po stronie serwera, niezależnie od tego, który przycisk został naciśnięty, ale często, jeśli dostępne są dwie akcje po stronie użytkownika, będą one mapowane również na dwie akcje po stronie serwera.

Edycja: Jak zauważył Pascal_dher w komentarzach, ten atrybut jest również dostępny w <input>tagu.

Lew
źródło
1
Dostępne również dla znacznika „input”. Przypisywanie do w3schools: podczas używania znacznika przycisku różne przeglądarki mogą przesyłać różne wartości: w3schools.com/tags/tag_button.asp
Pascal_dher
3
Od 12 lat jestem programistą, a ten jest dla mnie nowy i był dokładnie tym, czego potrzebowałem. Dzięki!
KyleFarris
1
Nie ma za co @KyleFarris! Wierzę, że stało się to możliwe stosunkowo niedawno, więc nie jest zaskoczeniem, jeśli jeszcze się z tym nie spotkasz.
Leo
2
Uwaga dla użytkowników Railsów: dodanie tego atrybutu nie będzie działać, jeśli formularz zostanie utworzony przy użyciu form_tag. Jedynym sposobem, w jaki udało mi się go uruchomić, jest przełączenie się form_fori używanie f.submit formaction: 'your_path'.
fgblomqvist
2
formactionw MDN
akinuri,
27

Jest to niezwykle łatwy do przetestowania

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

Po prostu umieść to na stronie HTML, kliknij przyciski i spójrz na adres URL

Peter Bailey
źródło
5
Korzystanie z GET tutaj jest dość złą praktyką, należy używać POST, jeśli to możliwe.
Syncrossus
6
@Syncrossus To do celów testowych.
Etienne Martin
22

Użyj formactionatrybutu HTML (5. linia):

<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
źródło
2
Jest to podobne do wcześniejszej odpowiedzi Leo .
ToolmakerSteve
@ToolmakerSteve - Ale użytkownicy pozytywnie ocenili . wybierz swój wybór !!
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
źródło
Funkcja HTML5. Działa idealnie w najnowszych przeglądarkach internetowych, dzięki!
Stephane Lallemagne
1
UWAGA: Wygląda to tak samo, jak wcześniejsza odpowiedź Leo , z tym wyjątkiem, że pokazuje użycie inputtagu zamiast buttontagu.
ToolmakerSteve
11

Najlepszym sposobem radzenia sobie z kilkoma przyciskami przesyłania jest użycie przypadku zmiany w skrypcie serwera

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

kod serwera / skrypt serwera - w przypadku przesyłania formularza:

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

?>

Źródło: W3Schools.com

Shailesh Sonare
źródło
tak, musisz mieć pojęcie o skryptach akcji (technologia skryptów po stronie serwera) Możesz użyć dowolnego skryptu / pliku do przetworzenia przesłanych danych, np. php, asp, jsp itp. <form action="demo_form.php" method="get">
Shailesh Sonare
W porządku. Było to mylące, ponieważ istnieje również język o nazwie ActionScript. Zamiast tego powinieneś powiedzieć: „kod serwera” lub „skrypt serwera”.
Civilian
Nie miałem pojęcia, że ​​można to zrobić za pomocą przycisków
William Isted
10

Być może zaproponowane tutaj rozwiązania zadziałały w 2009 roku, ale przetestowałem już wszystkie te pozytywne odpowiedzi i nikt nie działa w żadnej przeglądarce.

Jedyne rozwiązanie, które działało, to: (ale myślę, że jest trochę brzydkie w użyciu)

<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
źródło
2
Dlaczego nie po prostu użyć formaction="actionurl1"? Nie potrzebujesz JavaScript.
rybo111
3
@ Rybo111 IE9 przeglądarka (czarownica jest wciąż stosunkowo szeroko stosowana) nie obsługujeformaction
clueless007
1
@inaliaghle Prawda, to około 1% użytkowników - zależy od kogo jest skierowany projekt. Około 1% użytkowników nie używa JavaScript.
rybo111,
1
Dla przyszłych czytelników: nie ma nic złego w korzystaniu z javascript, jak w tej odpowiedzi. To przydatna umiejętność. OTOH, bardziej uprzywilejowane odpowiedzi również działają dobrze - zignoruj ​​wiodące zdanie tej odpowiedzi. Jeśli z jakiegoś powodu nie możesz uzyskać odpowiedzi na te inne pytania, opublikuj cały kod jako pytanie SO, wyjaśnij, co się dzieje (lub nie nastąpi) i zapytaj, co robisz źle.
ToolmakerSteve
6

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

Przykładowy kod serwera (PHP):

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

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

elseifbardzo ważne, ponieważ oba zostaną przeanalizowane, jeśli nie. Cieszyć się.

Thielicious
źródło
Jest to doskonała sugestia - głównie dlatego, że możesz bardzo łatwo dodać więcej przycisków z większą liczbą przypadków i użyć switchdomyślnej akcji, jeśli ktoś dodał przycisk i zapomniał dodać go do switch(i / lub źle napisał coś itp.)
Gwyneth Llewelyn
Ponadto @Pato dodał podobną odpowiedź, która jest prawdopodobnie bardziej idiomatyczna, ale twoja działa dobrze!
Gwyneth Llewelyn
1
@GwynethLlewelyn Nie widziałem drugiej odpowiedzi ani nie zauważyłem, kiedy napisałem własną. To właściwie to samo, ale to po prostu podkreśla, że ​​większość ludzi woli tę logikę. Różnica polega tylko na nazwach z powodów semantycznych, dobrym zrozumieniu dla początkujących lub kogokolwiek, kto chce zacząć od tego.
Thielicious
5

Ponieważ nie określiłeś, jakiej metody skryptowej używasz na serwerze, dam ci przykład, który działa dla Pythona, używając CherryPy (chociaż może być przydatny również w innych kontekstach):

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

Zamiast używać wartości do ustalenia, który przycisk został naciśnięty, możesz użyć nazwy ( <button>zamiast tagu zamiast <input>). W ten sposób, jeśli twoje przyciski będą miały ten sam tekst, nie spowoduje to problemów. Nazwy wszystkich elementów formularza, w tym przycisków, są wysyłane jako część adresu URL. W CherryPy każdy z nich jest argumentem dla metody wykonującej kod po stronie serwera. Tak więc, jeśli twoja metoda ma tylko **kwargslistę parametrów (zamiast żmudnego wpisywania każdej pojedynczej nazwy każdego elementu formularza), możesz sprawdzić, który przycisk został naciśnięty w ten sposób:

if "register" in kwargs:
    pass #Do the register code
elif "login" in kwargs:
    pass #Do the login code
Brōtsyorfuzthrāx
źródło
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
źródło
2

Myślę, że powinieneś być w stanie odczytać nazwę / wartość w tablicy GET. Myślę, że przycisk, który nie został kliknięty, nie pojawi się na tej liście.

John Bubriski
źródło
Najprawdopodobniej masz na myśli tablicę POST.
ypnos
3
Niekoniecznie, jeśli metoda formularza to „POST”, nie pojawi się w tablicy GET. Większość formularzy jest przesyłana za pośrednictwem POST.
Papugi
2
Albo / lub jest technicznie poprawny, a jednak bardzo zły. Możesz przesłać formularz przy użyciu metody = "GET", ale jest to godne uwagi.
Bill the Lizard
4
Jest tylko „godny uwagi”, gdy jest niewłaściwie używany: w3.org/2001/tag/doc/whenToUseGet.html .
mercator,
2
Tak, nie próbowałem sugerować GET, tylko próbowałem uogólniać.
John Bubriski
1

Możesz to zrobić w ten sposób (myślę, że jest to bardzo wygodne, jeśli masz N wejść).

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

Typowym przypadkiem użycia byłoby użycie różnych identyfikatorów z bazy danych dla każdego przycisku, abyś mógł później dowiedzieć się na serwerze, który wiersz został kliknięty.

Po stronie serwera (w tym przykładzie PHP) możesz odczytać „wiersz” jako tablicę, aby uzyskać identyfikator. $_POST['row']będzie tablicą zawierającą tylko jeden element, w formie [ id => value ](na przykład [ '123' => 'something' ]:).

Aby uzyskać kliknięty identyfikator, wykonujesz:

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

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

Pato
źródło
Jest to podobne do odpowiedzi @Thielicious pisał , ale twój jest prawdopodobnie bardziej idiomatyczne. Osobiście wolę używać tagów alfanumerycznych dla indeksu (w przeciwieństwie do liczb) dla czytelności (łatwiej zapamiętać, co powinien robić każdy przycisk), ale YMMV. Ale wykorzystanie $_POST['row']bycia tablicą asocjacyjną jest sprytne!
Gwyneth Llewelyn
1
Zgadzam się, że jeśli masz do czynienia z przyciskami statycznymi, powinieneś używać nazwanych kluczy. Ale w niektórych przypadkach nie możesz. Czasami generujesz te dane wejściowe dynamicznie. Najczęstszym przypadkiem tego jest lista wierszy, z których każdy jest identyfikowany przez identyfikator. Myślę, że myślałem o tej sprawie, kiedy napisałem odpowiedź (4 lata temu!). Zredagowałem go, więc jest bardziej oczywiste, że liczba jest identyfikatorem, a nie indeksem.
Pato
Dobra robota! Tak, zgadzam się, teraz jest to bardziej oczywiste; Nadal uważam, że twoja odpowiedź jest nieznacznie lepsza niż odpowiedź @Thielicious (i być może nawet bardziej wydajna, szczególnie jeśli jest wiele przycisków).
Gwyneth Llewelyn
1

Zgłaszasz przycisk wielokrotnego przesyłania w jednym przykładzie formularza

 <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
źródło
0

Proste, możesz zmienić działanie formularza na różnych przyciskach przesyłania Kliknij.

Spróbuj tego w dokumencie

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

$(".declineOffer").click(function () {
       $("form").attr("action", "/Sales/SubdomainTransactions");
});
Slan
źródło
0

Możesz także użyć atrybutu href i wysłać get z wartością dołączoną do każdego przycisku. Ale formularz nie byłby wtedy wymagany

href="/SubmitForm?action=delete"
href="/SubmitForm?action=save"
Jonathan Laliberte
źródło
Nie działałoby to dla kontrolerów w POSTtrasach.
Xavi Montero
stąd „wyślij dostań”
Jonathan Laliberte
3
Przepraszam, że się nie zgadzam, ale GETnie zawsze jest to odpowiednie. Jeśli „zmodyfikujesz stan swojego modelu”, nigdy nie powinieneś używać a GET, ponieważ odświeżenie przeglądarki może dać przezroczyste przesłanie dwa razy tego samego żądania. Używaj GETtylko do „przeglądania” rzeczy i POSTwysyłania żądań zmian stanu (dodawania, usuwania, edycji itp.). następnie w POSTakcji kontrolera zmień stan (baza danych, sesja ...) i nadaj odpowiedź przekierowującą, która następnie zmieni GETnowy stan. Robienie GETzmian stanu modelu jest bardzo brudne i każdy dobry programista powinien tego unikać. Przykro mi to mówić. Reguła czyszczenia kodu.
Xavi Montero
Prawdziwe. Ale granie w brud może czasem być czyste. To zależy od tego, co dokładnie robisz. Osobiście nie mapowałbym żądań usunięcia i edycji w get, ale istnieją sposoby, aby to działało. Np. Sprawdzenie, czy zostało już usunięte, czy sprawdzenie, czy użytkownik ma na to pozwolenie itp.
Jonathan Laliberte
-1

Możesz przedstawić przyciski w następujący sposób:

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

A następnie w kodzie możesz uzyskać wartość, używając:

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

(valUnits i valPrice to niektóre inne wartości, które wyodrębniłem z formularza, który zostawiłem dla ilustracji)

użytkownik3714578
źródło
-1

Ponieważ nie określiłeś, jakiej metody skryptowej używasz na serwerze, dam ci przykład, który działa dla 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>

Formularze

Po kliknięciu opcji Login -> loginForm

Po kliknięciu Zapisz -> saveForm

Po kliknięciu opcji Zarejestruj -> formularz rejestracyjny

Pradip Kumar Raushan
źródło