How can I add a custom form submission handler?

I tried adding $form['#submit'][] = 'mymodule_form_submit'; or $form['actions']['submit']['#submit'][] = 'mymodule_form_submit'; to hook_form_alter().

use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\HttpFoundation\Request;

function MYMODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'node_trends_form' || $form_id == 'node_trends_edit_form') {
    foreach (array_keys($form['actions']) as $action) {
      if ($action != 'preview' && isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] === 'submit') {
        $form['actions']['submit']['#submit'][] = 'mymodule_form_submit';
function mymodule_form_submit(array $form, FormStateInterface $form_state){
    //die("why won't this execute? :(");
    drupal_set_message("Why won't this message show?");

It seems drupal_set_message() is not called. I also tried rebuilding the cache, but the function is still not called.

I am using Drupal 8.2.3.

  • You should show the full implementation of hook_form_alter(), or it's a bit harder to tell you what you are doing wrong. Also, you should say which form you are trying to alter. – kiamlaluno Dec 19 '16 at 16:51
  • @kiamlaluno I add my hook_form_alter. – Yusef Mohamadi Dec 19 '16 at 16:56
  • what's your code still $form['actions']['submit']['#submit']? Try replace ['submit'] with [$action]. – MrD Dec 19 '16 at 17:10

If you use hook_form_node_form_alter() may be use example code:

function mymodule_form_node_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  foreach (array_keys($form['actions']) as $action) {
    if ($action != 'preview' && isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] === 'submit') {
      $form['actions'][$action]['#submit'][] = 'mymodule_form_submit';

and submit function

function mymodule_form_submit(array $form, FormStateInterface $form_state){
    //die("I'm not getting run, why :(");
    drupal_set_message("Why won't this message show?");


Creating a custom webform handler plugin for drupal 8.

This document assumes you've already installed and enabled webform and webform-ui

1) Create your webform. - Go to structure -> webforms and press the "+ Add webform" button. - You can either use the ui or use yaml, that's up to you. example yaml for a one field form that takes an email address:

  '#type': email
  '#title': email
  '#title_display': invisible
  '#placeholder': 'ENTER YOUR EMAIL'
      - my-ip

The indentation is important for yaml so make sure you get it right. indents are spaces.

Now save your form.

2) Creating a webform handler plugin

Next we can create a new plugin which will show up in the "Emails/Handlers" section when editing the webform. I will call it myhandler, you can call it what you want, provided you replace all mentions of myhandler with the name you pick.

a) Create a new folder for your plugin, do this in your drupal root (referred to here as /var/www/html/) in the following subfolder: /var/www/html/modules/Custom/myhandler

b) Create a new file in the above directory called myhandler.info.yml in this file goes the following:

name: My Form Handler
description: handles form submits, does something with them. 
package: Custom
type: module
version: 1.0
core: 8.x

3) Create a src directory in your module directory, eg: /var/www/html/modules/Custom/myhandler/src in src create Plugin in Plugin create WebformHandler

(this can be achived in one go using

mkdir -p /var/www/html/modules/Custom/myhandler/src/Plugin/WebformHandler/ 

which will make the entire structure in one go using the -p flag to mkdir.)

4) Create a new file /var/www/html/modules/Custom/myhandler/src/Plugin/WebformHandler/MyFormHandler.php

in that file goes the following php code, i've left the config form setup in so you can see how to configure your plugin if needed.

namespace Drupal\myhandler\Plugin\WebformHandler;

use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Serialization\Yaml;
use Drupal\Core\Form\FormStateInterface;
use Drupal\webform\Plugin\WebformHandlerBase;
use Drupal\webform\webformSubmissionInterface;

 * Form submission handler.
 * @WebformHandler(
 *   id = "myhandler_form_handler",
 *   label = @Translation("MyHandler form handler"),
 *   category = @Translation("Form Handler"),
 *   description = @Translation("Do something extra with form submissions"),
 *   cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_SINGLE,
 *   results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
 * )
class MyFormHandler extends WebformHandlerBase {

       * {@inheritdoc}

     public function defaultConfiguration() {
        return [
            'submission_url' => 'https://api.example.org/SOME/ENDPOINT',

     * {@inheritdoc}
    public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
        $form['submission_url'] = [
            '#type' => 'textfield',
            '#title' => $this->t('Submission URL to api.example.org'),
            '#description' => $this->t('The URL to post the submission data to.'),
            '#default_value' => $this->configuration['submission_url'],
            '#required' => TRUE,
        return $form;

   * {@inheritdoc}
  public function submitForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
    // Your code here.
        // Get an array of the values from the submission.

        $values = $webform_submission->getData();

        // Get the URL to post the data to.
        $post_url = $this->configuration['submission_url'];

        $message = "MyHandler got form data:".print_r($values,1); 

        return true;

5) Enable your MyHandler module (using drush or extend menu) and then rebuild your drupal cache ( "drush cr" from anywhere under your drupal root (/var/www/html here) would do that if you use drush )

6) edit your webform, go to "Email / Handlers" and click on "+ Add Handler" button You should see your plugin listed, click Add Handler, you should now see a box asking for the submission url. click Save button. If something doesn't look right, or it isn't working, check the apache error log, you might find something helpful there.

7) Test your form - make a submission to the form, and then check the watchdog log (drush ws), you should see the values sent to it. They might be truncated in the output you see, don't panic, it's all there. What you do with this now is up to you.

Hope this helps someone. I cobbled it together from stuff I found around the place and wrote it into a single document. Thanks to the others who got me here.

  • If I get it right, the one minor thing that's missing in the above code for the handler to work correctly is the submitConfigurationForm() method, consisting of parent::submitConfigurationForm($form, $form_state); and parent::applyFormStateToConfiguration($form_state);. – Hendrik Mar 31 '18 at 16:49
  • @Hendrik No, you don't need it. I've created a new handler with only a submitForm() function and it works. All other functions are situated in the base class and I have no needs to override they. By the way: a quite nice a simple solution once you figure it out ;-) – RWAM Jul 5 '18 at 9:49

if using hook_form_BASE_FORM_ID_alter in Drupal 8 core 8.4.3, I found the ways of adding the custom submit handler didn't work. This worked for adding the submit handler function name:

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

In another situation, using hook_form_FORM_ID_alter in Drupal 8.4.5, I found the above did not work for adding the custom submit handler. Instead, this worked:

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

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.