15

I have a form with a "Submit" and a "Cancel" buttons. In hook_submit(), how do I know which button was clicked?

1
  • Are you talking of hook_submit() or a form submission handler? A form submission handler is not the implementation of hook_submit().
    – apaderno
    Jul 20, 2011 at 15:30

7 Answers 7

27

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.

1
  • 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.
    – Neil Davis
    Apr 5, 2020 at 19:44
7

$form_state['clicked_button']['#value'] will tell you which button was clicked on the form.

7
  • $form_state['clicked_button']['#value'] :)
    – user1359
    Jul 20, 2011 at 15:20
  • 1
    I 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/…
    – iStryker
    Jul 20, 2011 at 15:25
  • That's a good point!
    – user1359
    Jul 20, 2011 at 15:26
  • 5
    While "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
  • 1
    While 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
6

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.

1
3

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.
1
  • 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 ?
    – Gaius
    Apr 19, 2016 at 8:41
2

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
}
7
  • If I remember correct Drupal 6 $form_state]['X'] is now $form_state['X'] in Drupal 7
    – iStryker
    Jul 20, 2011 at 14:50
  • Why do you need to compare these two values?
    – iStryker
    Jul 20, 2011 at 14:56
  • 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
    @iStryker I am not sure what you mean with your first comment.
    – apaderno
    Jul 20, 2011 at 15:29
2

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.

0

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

1
  • Don't translate the #name, or if you do you must translate it in the if too. Sep 28, 2021 at 14:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.