I'm having issues calling an existing form from the commerce_coupon module which runs a default submit handler callback (commerce_coupon_form_submit).

My form builds off of that form and simply tries to replace the default '#submit' value to call my own submit function instead of the default commerce_coupon one. I'm using drupal_get_form so my code looks like the following:

$form = drupal_get_form('commerce_coupon_form', $coupon);
$form['#submit'] = array('mymodule_coupon_submit');
return drupal_render($form);

That is the code from inside a function that is supposed to return the rendered form. The problem is the default commerce_coupon_form_submit submit handler is still running and my own function doesn't get called. I think this has something to do with the form_id or form_state still being commerce_coupon_form.

I've found related problems on stackexchange but responses were directed for other versions of Drupal. I'm using D7 so please bear that in mind.

I'm adding a little more detail that may help get a better answer for this. The original commerce_coupon_form seems to try to use a button-level #submit handler as there is the following before the form is returned:

$form['actions'] = array(
    '#type' => 'container',
    '#attributes' => array('class' => array('form-actions')),
    '#weight' => 400,
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save coupon'),
    '#weight' => 40,

but the actual #submit handler isn't assigned so the default drupal handler is being set at the root of the form. I've tried assigning a button-level submit and overriding the root drupal assigned submit to a blank array but that doesn't seem to work. I'm trying to track down documentation for drupal or the function that sets the default #submit so I can figure this out. If you can point me in the right direction I would appreciate it.

  • print_r($form['#sumbit']) after you assign it your fuction. has it only one element of array? – Yuseferi Sep 12 '12 at 18:03
  • Yeah I'm using devel and dpm($form['#submit']) shows an array with only the element, mymodule_coupon_submit. – edgji Sep 12 '12 at 18:07
  • please wait, I test it by myself and found a way to solve it – Yuseferi Sep 12 '12 at 18:10
  • really what you want, run your function and default submit or only your function (unset default submit) ? – Yuseferi Sep 12 '12 at 18:37

The problem is when the form builder builds the form up again when it's submitted, your function won't be called so it doesn't know about the changes you've made.

hook_form_alter() (and hook_form_FORM_ID_alter()) were written for exactly this purpose, I'd advise using one of those, e.g.

function MYMODULE_form_commerce_coupon_form_alter(&$form, &form_state, $form_id) {
  $form['#submit'] = array('mymodule_coupon_submit');

It's worth bearing in mind that other modules' hooks might run after yours and change that array again. To avoid that have a look at How to update a module's weight.

  • Would there be an easy way to manipulate the form ID as that seems to be a way around the problem of the form builder rebuilding the form on submission. Is there documentation on the flow/ process of the form builder? – edgji Sep 12 '12 at 18:36
  • Not that I know of, as far as I know the form builder needs to rebuild the form upon submission (maybe unless #cache has been set to true, I'm not sure). I've never seen any good documentation on the FAPI workflow but there might be some out there; I just bit the bullet and learnt it by following the functions (starting with drupal_get_form()) and reading all the comments along the way – Clive Sep 12 '12 at 18:39

You need first unset defaut #submit array

 $form = drupal_get_form('commerce_coupon_form', $coupon);

unset( $form['actions']['submit']['#submit']);
// or empty it

$form['#submit'] = array('mymodule_coupon_submit');
return drupal_render($form);
  • Hmm I'm doubting what I said now...have you tested this to work? – Clive Sep 12 '12 at 18:31
  • I mentioned that $form['actions']['submit']['#submit'] isn't actually set in the original form so unsetting it or emptying it isn't actually necessary. – edgji Sep 12 '12 at 18:31
  • sorry, I thought you want unset default submit, by this code default drupal sumbit won't run. – Yuseferi Sep 12 '12 at 18:37

On suggestion of @Clive I dug through some of the functions that the Drupal form builder works off of. The easy way to get this done was to build a wrapperform so essentially my own form. To load the original commerce_coupon_form's elements I used drupal_retrieve_form so my end result looks something like this

function mymodule_custom_wrapper_form($form, &$form_state, $coupon) {
  $form = drupal_retrieve_form('commerce_coupon_form', $form_state);
  return $form;

I end up calling drupal_get_form with my own mymodule_custom_wrapper_form as the form_id argument. Now drupal adds default submit callbacks based on my forms id. That works for now for pulling in form elements from an existing form but I'm still looking for a way to have the original form's hooks remain intact. I'm guessing that will be a greater feat since I just got rid of the core of the original form's functionality by not using drupal_get_form directly on the original form. For anyone else trying to implement a type of form within a form this is a good start but there is a module I stumbled into. http://drupal.org/project/subform might be an easier approach to accomplish something similar.

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.