12

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

  • Are you talking of hook_submit() or a form submission handler? A form submission handler is not the implementation of hook_submit(). – kiamlaluno Jul 20 '11 at 15:30
23

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.

7

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

  • $form_state['clicked_button']['#value'] :) – user1359 Jul 20 '11 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 '11 at 15:25
  • That's a good point! – user1359 Jul 20 '11 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. – Bojan Zivanovic Aug 17 '11 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. – Alice Heaton Jun 20 '13 at 8:50
3

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 – iStryker Jul 20 '11 at 14:50
  • Why do you need to compare these two values? – iStryker Jul 20 '11 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. – Shoaib Nawaz Jul 20 '11 at 15:10
  • A single comparison is best to avoid all language comparisons in multilingual setup. :) – Shoaib Nawaz Jul 20 '11 at 15:15
  • 1
    @iStryker I am not sure what you mean with your first comment. – kiamlaluno Jul 20 '11 at 15:29
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.
  • 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 '16 at 8:41
3

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.

0

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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