How to add one or more custom submit handlers to a Drupal form
The information in this post relates to Drupal 5.x.
In Drupal 5 it's possible, and easy, to play with a form's submit handlers: you can replace an existing handler with your own and you can even add multple handlers if you want.
In human terms, this means that you can change the function that is called when a certain form is submitted and has passed the validation handler (the function responsible for validating the form input).
Why would you want to do this?
You might want to do some stuff before a node is inserted, like insert the same data into an external database. Maybe you want to change the submitted information before it's handled by Drupal. Maybe you want to send a mail to a certain user when a certain type of node is updated with certain information.
Or maybe you want to interrupt the normal flow and just do something totally different than normally intended.
Whatever you want to do, you can do it all by using your own submit handlers. Here's how:
Each form has a #submit property. The value of that property is the name of the function that is to be called on submit. If this property is not present, Drupal will look for a function called form_id_submit. If that one isn't found either, Drupal will look for a function called #base_submit.
Tip: chapter 10 of Pro Drupal Development does a great job of describing the Form API in detail.
If you want to override this value, simply replace the #submit value with a function name of your choice. You need to do this by implementing a form_alter hook. This means creating a function that will be called when a your form is called, making sure to respect the naming convention and the function"s signature (number and order of parameters)
Example:
function mymodule_form_alter($form_id, &$form){
switch($form_id){
case 'some_form_id':
// code in here will be called when form 'some_form_id' is built.
// this is your chance to modify it before its html is rendered.
break;
}
}
The code to modify the submit handler:
$form['#submit'] = 'mymodule_my_own_submit_handler';
Now, what's cool is that you can queue up multiple submit handlers, meaning that you can have multiple functions called one after the other, upon a form submit. To do this, simply put them in an array and assign it to the #submit property:
$form['#submit'] = array( 'mymodule_my_own_submit_handler', 'mymodule_my_second_submit_handler', 'mymodule_my_third_submit_handler');
If you simply want to add a submit handler, but want to make sure it is executed before the default handler, you need to do something like this:
// add an additional submit handler to the #submit array.
// use array_merge to make sure the new handler is the first one in the array
$form['#submit'] = array_merge(array("mymodule_my_handler" => array()), $form['#submit']);
Putting it all together:
function mymodule_form_alter($form_id, &$form){
switch($form_id){
case 'some_form_id':
$form['#submit'] = 'mymodule_my_own_submit_handler';
break;
}
}
Have fun.
Comments
Spot on mate with the additional handler in the submit. Very useful.
Thanks. Took me a bit of time to figure out but in the end it's quite straightforward.
Thanks
Lifesaver!
So cool to be able to chain submit handers! Thanks for posting this, excatly what I was looking for. Now I can process a single select value where the OG form handler was expecting multiple values.
-M
Thanks so much! I've been looking for this site for an hour! I didn't know how to add a submit handler rather than override the original one. I don't aspire to completely replace the functionality of the node module...
So, that was amazingly helpful. God bless you!
you're quite welcome :)
Great post!
One question though, how would I do something with say, for example, an additional field that I add in the form_alter hook?
Example: I'm altering a simple form that normally asks for a First and Last name, but I am writing a simple module that adds an additional Title field.
If I use something like:
$form['#submit'] = array_merge(array("my_module_handler" => array()), $form['#submit']);
Can I pass something like $form_values['title'] through to the handler as an argument to save into a custom table?
I know the article clearly states that the information is for Drupal 5.x, but those using Drupal 6.x need to use the following code:
$form['#submit'] = array('my_form_handler');
The only difference is that all form handlers, regardless it it's one or many, must be in an array. I hope someone finds this helpful.
Hello, this is working for drupal 6.x also. now i have another problem. When i do
[code]
function modulename_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'modulename1_node_form') {
$form['#submit'][] = 'modulename_getpkid';
}
return $form;
}
function modulename_getpkid(&$form, &$form_state) {
$sid = $form_state['values']['sid'];
print $sid;die;
}
[/code]
it is not working. do you have any idea why ? what i m trying is to save values of latest id stored in database by pressing submit button.
Hats off for the _form_alter idea, man. I was trying to find a way to have a form with two submit buttons, where one submits to the form itself (it's a multistep) and another one that jumps to a different URL, but sending the values via POST to that URL. Here's how I'll do it:
I'll intercept the form submission, and according to the value of the $form['op'] (the button pressed), I will change the $form['#action'] property. Hope it will work. Thanks for the inspiration.
Post new comment