Thursday, 23 October 2014

Adding a submit callback to an entity form

If you use hook_form_alter(), hook_form_FORM_ID_alter(), or even hook_form_BASE_FORM_ID_alter() to intercept an entity add/edit form and you want to add a #submit callback, then this:

$form['#submit'][] = 'my_module_extra_submit';

won't work. But this will:

$form['actions']['submit']['#submit'][] = 'my_module_extra_submit';

Because the submit callbacks are added to the button and not the form. The same applies to #validate though as usual you're better off adding '#element_validate' to the element you want to check, if possible.

But that probably won't be enough because the default content of the submit callbacks is:

array('::submitForm', '::save')

If you're making a change to the entity you can't add your callback on the end of the array because the entity has already been saved, and your change will make no difference.

Nor can you unshift it on to the start because ::submitForm() overwrites the entity with a new one constructed from the form values. So any change will be wiped out.

You have to insert it just before the ::save(), this code will do the trick:

  // Have to add the submit callback to the button submit on an entity form
  // but it has to go after the '::submitForm()' and before the '::save()'.
  $submits =& $form['actions']['submit']['#submit'];
  $key = array_search('::save', $submits, TRUE);
  array_splice($submits, $key, 0, array('my_module_extra_submit'));

Things to bear in mind here is that the 4th parameter to array_splice() is cast to an array if it isn't one, which could result in strange behaviour if you're using a callback to a method, in which case you need array(array('myClass', 'myMethod')).


The entity form class creates a base_form_id, which is the entity id plus "_form" (e.g. "node_form") which is also called in the form alter sequence. It means you can have a single hook to handle both add and edit forms.

If the base form id would be the same as the form id, it doesn't perform the extra call because that would result in a hook function being called more than once.

Don't forget to sign-up to get information about my Drupal 8 book(s).

No comments:

Post a Comment