I have a form with a "Submit" and a "Cancel" buttons. In hook_submit()
, how do I know which button was clicked?
7 Answers
You must use the triggering_element
from the $form_state['triggering_element']
.
Best practice is to define a #name
attribute for your button, so you can have this value in the triggering_element
.
For example:
$form['delete'] = array(
'#type' => 'submit',
'#value' => t('Delete'),
'#name' => 'delete',
);
If you don't define this attribute triggering_element
will hold the button's #value
(the text that user can read), but this is discouraged as other modules may change this value or be changed by the localization).
You may use $form_state['clicked_button']
too, but this is deprecated.
You can read more info at the drupal_build_form function documentation page.
-
As of Drupal 8.8(maybe earlier) you use $form_state->getTriggeringElement()['#value'] (or #name or whatever triggering_element array index you want). Accessing $form_state properties directly as an array element reference will now throw an error. Apr 5, 2020 at 19:44
$form_state['clicked_button']['#value']
will tell you which button was clicked on the form.
-
-
1I like to add, if you have required field(s) on your form, and they are not filled in, then you Drupal will thrown a form validation error (form_submit is called after form_validate). You need to do something like this devengineering.com/best-practices/drupal/…– iStrykerJul 20, 2011 at 15:25
-
-
5While "clicked_button" still works, it has been deprecated in D7 and the recommendation is to use "triggering_element" instead. I remember there were some #ajax bugs (I think) that only affected code that used "clicked_button", so that's one more reason to use "triggering_element". And after all, it's just a different key in $form_state. Aug 17, 2011 at 11:14
-
1While this approach works, it is deprecated and prone to problems. See tunic's answer for the correct Drupal 7 way to do this. Jun 20, 2013 at 8:50
UPDATE 2016 Drupal 8
For those still trying to figure out how to access the triggered event here is the Drupal 8 solution.
$form_state->getTriggeringElement()
This returns the array of the triggering submit element. If you add a markup called #name
then you would access it with the following way.
$button_clicked = $form_state->getTriggeringElement()['#name']
The reason behind this change is that FormStateInterface
is now a readOnly
file in which only classes that extend FormStateInterface
can access the variables. So you have to use accessor methods like getTriggeringElement()
in order to access the variable.
-
I have an update for Drupal 8.4.4 in 2018: drupal.stackexchange.com/a/256112/1441– user1359Feb 19, 2018 at 18:55
Compare these values in $form_state
I have been doing in Drupal 6 and would be same in Drupal7
if($form_state['values']['ok'] == $form_state]['clicked_button']['#value']){
//Process if OK is pressed
}else if($form_state['values']['cancel'] == $form_state]['clicked_button']['#value']) {
//Process if Cancel is pressed
}
-
If I remember correct Drupal 6 $form_state]['X'] is now $form_state['X'] in Drupal 7– iStrykerJul 20, 2011 at 14:50
-
-
If form contains multiple submit buttons. This comparison will help to differ which button used to submit the form in a single submit handler. $form_state['clicked_button']['#value'] = t('Yes') will result different values on multilingual setup. Jul 20, 2011 at 15:10
-
A single comparison is best to avoid all language comparisons in multilingual setup. :) Jul 20, 2011 at 15:15
-
1
Name the buttons with the #name
attribute, like this:
$form['delete'] = array(
'#type' => 'submit',
'#value' => t('Delete'),
'#name' => 'delete',
);
and then use:
$values = $form_state['input'];
if (isset($values['delete'])) // 'delete' button was pressed.
-
So for a form with two submit button like this : $form['submit'] = array( '#type' => 'submit', '#name' => 'submit-1', '#value' => t('Submit1'), ); $form['submit2'] = array( '#type' => 'submit', '#name' => 'submit-2', '#value' => t('Submit2'), ); We just have to check $form_state->getTriggeringElement()['#name'] in the submitForm() function ?– GaiusApr 19, 2016 at 8:41
In Drupal 8.4.4 $form_state->getTriggeringElement()['#name'];
gives you the value of op
. When you look for that key in the form state's values array, you get the #value
key of the button form element-- in other words, the string that the end users sees on the button on the page.
I don't know if $form_state->getValues()['op']
is universal for all forms, but I'm hard-coding it in my module's form.
Drupal 8.6.7
Create button something like below.
$form['my_button'] = [
'#type' => 'button',
'#value' => t('Custom Button'),
'#name' => t('customButton'),
'#weight' => 0,
'#attributes' => [
'class' => ['populate-bib-button', 'btn', 'btn-primary'],
],
];
In your submit function get button name like below code.
$input = $form_state->getUserInput();
print $input['_triggering_element_name']; // customButton
Comparison can be done like
if ($input['_triggering_element_name'] == 'customButton') {
// Do something.
}
#Drupal8
-
Don't translate the #name, or if you do you must translate it in the if too. Sep 28, 2021 at 14:39
hook_submit()
or a form submission handler? A form submission handler is not the implementation ofhook_submit()
.