3

I have two submit buttons on my form. One is the normal submit button that calls `my_form_submit` like-ah-so:

$form['fieldset']['submit'] = array(
  '#type' => 'submit',
  '#value' => 'Show Applications',
);

I want to add another button that will submit the form, but call a different submit handler. Is there any way to do this? I have looked at adding the #submit property to an element like-ah-so:

$form['fieldset']['evil_plan'] = array(
  '#type' => 'submit',
  '#value' => 'Big Red Button',
  '#submit' => array('steal_formula_for_icantbeliveitsnotbutter'),
);

hoping to call the `steal_formula_for_icantbeliveitsnotbutter` function but no worky. When I click the Big Red Button the normal `my_form_submit` function is called, which sets back my plan to make millions off of a butter substitute. Who can shed some light on this dark mess?

googletorp
  • 33,075
  • 15
  • 67
  • 82
Jamison Dance
  • 19,896
  • 25
  • 97
  • 99

2 Answers2

4

for Drupal 5, this is the only solution:

function my_form_submit($form_id, $form_values) {
  if ($form_values['op'] == 'Show Applications') {
    // handle 'Show Applications' submission
  }
  elseif ($form_values['op'] == 'Big Red Button') {
    // handle 'Big Red Button' submission
  }
}

same for my_form_validate.

in Drupal 6, this can easier be done with the newly introduced custom #submit and #validate handlers for form buttons.

ax.
  • 58,560
  • 8
  • 81
  • 72
  • I was trying to avoid doing it in the same submit function. Is there really no way to redirect it to a different submit function without going through the normal one? – Jamison Dance Sep 11 '09 at 18:38
  • +1, as this was the initial and correct answer fro Drupal 5! (Now if you just had mentioned that you checked the 5/6 difference, I wouldn't have interfered in the first place ;) – Henrik Opel Sep 14 '09 at 16:24
  • always trying to be as concise as possible :) tnx for the +1. – ax. Sep 14 '09 at 16:58
  • Yeah, premature selection of the correct answer, but I gave you a plus one. Sorry about that! – Jamison Dance Sep 17 '09 at 03:59
3

Edit: A closer check of the Forms API Documentation revealed that my initial answer below is valid for Drupal 6, but only partially valid for Drupal 5. Comparing the Drupal 5 docs with the Drupal 6 docs shows that in Drupal 5, you can only register callback functions on the form itself - the '#submit' property of a button is just a boolean indicating that the button is to be handled as a submit button. So adding 'per button' callbacks is a Drupal 6 only feature!

For the given Question, this means that there is only the if/elseif option suggested by ax, or the variation of registering two submit callbacks for the form, each checking if they are called for the right button (basically the if/elseif version, but using two separate callbacks).


(initial answer)

There are several mechanisms at work here:

  1. Submit (and validate) callbacks can be registered for individual buttons, but also for the form itself ($form['#submit']). The ones registered for the form get called for every submit button, the ones registered for an individual button only for that one. (NOTE: Important Drupal 5/6 difference here, see edit below.)
  2. The default form handling (submit and validate functions named after the form) works by Drupal automatically adding callbacks for those to the forms '#submit' and '#validate' arrays.
  3. The registration uses arrays in order to allow for several submit/validate functions being called one after the other (in the same order they appear in the array).

So in your case, you could do the if/elseif switch suggested by ax, or you'd need to unset the 'global' callbacks for the form, moving it explicitly to the default submit button:

$form['fieldset']['submit']['#submit'] = $form['#submit'];
unset($form['#submit'];

(same thing for validate callbacks)

After that, your posted example for the Big Red Button executing the evil plan should work as expected ;)

Henrik Opel
  • 19,341
  • 1
  • 48
  • 64
  • That makes sense. So the $form['#submit'] (and validate) callbacks override the individual element ones. Is there a #validate callback I need to set as well? – Jamison Dance Sep 13 '09 at 19:34
  • Yup, validation follows the same mechanism, so if you need/use validation, you'd do the same for the validation callbacks. – Henrik Opel Sep 13 '09 at 20:49
  • Oups, just stumbled over a Drupal 5/6 difference in this context, see edit for details. – Henrik Opel Sep 13 '09 at 20:50
  • Sorry for the confusion - I'm on Drupal 6 for a while now and forgot about that difference. Also, in Drupal 6, the `$form['#submit']` would not *override* the button submit callback, but execute additionally. – Henrik Opel Sep 13 '09 at 21:03
  • what i was saying - i had checked on Drupal 5 vs. 6 :S – ax. Sep 14 '09 at 16:02
  • you might edit your answer putting the EDIT: at the top so someone looking for an answer doesn't try to implement the Drupal 6 solution for Drupal 5 before noticing it doesn't work. – ax. Sep 15 '09 at 06:10