Add a custom submission handler to a form

Solutions

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:

email:
  '#type': email
  '#title': email
  '#title_display': invisible
  '#placeholder': 'ENTER YOUR EMAIL'
  '#attributes':
    class:
      - 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.

<?php
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); 
        \Drupal::logger('myformhandler')->error($message);

        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 you use hook_form_node_form_alter() maybe use example code:

function MYMODULE_form_node_form_alter(&$form, \Drupal\Core\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 for the submit function use:

function MYMODULE_form_submit(array $form, \Drupal\Core\Form\FormStateInterface $form_state){
  //die("I'm not getting run, why :(");
  \Drupal::service('messenger')->addMessage("Why won't this message show?");
}

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';
Tags: Forms / Drupal 8

Similar questions

Why doesn't a form immediately call its submission handler?
I have a form which is called from a page function. The page initially makes some external calls to get #default_value data which gets passed to drupal_get_form(). When the form is submitted, the page function gets called before the submission handler. Why is that? I don't get it and I don't want that to happen because it then connects to an extern...
How do I alter the form submission handler?
For some reason I need to replace some characters (if exist) in every single textfields in any form just right before they stored in database. In other words I need a hook in which I could get all submitted data and replace their characters. I found this solution: But this isn't a good idea since I have to take care of the rest of the submission pr...
Execute user_save() after the form submission handler
In my implementation of hook_form_alter() I am using the following code; it executes mymodule_user_form_submit() before user_save(). user_save() is not executing after that. What is the problem with this code? I want to execute user_save() after mymodule_user_form_submit(). if the code is wrong how can i assign the value to this variable $form_stat...
why, when I call an AJAX callback, the form submission handler is also called?
I am trying to understand why, when I call an AJAX callback, the form submission handler is also called. I looked at the AJAX documentation and I see no mention of this behavior. Is this supposed to happen? How do I stop it?
Why doesn't my form submission handler work?
I am new to drupal and require help from Gurus. I am adding some form elements in the status share form by using hook_form_alter(). These elements are getting displayed in the form, but my submission handler is not working. I am using $form['#submit'][] = 'my_module_form_submit'; to add it to the form.
How do I use $form_state to return data from the from submission handler to the form builder?
I am trying to populate a data based on $form_state right after submission. What I am trying to do is to populate a form that takes a keyword and passes it to a function that gets the result from another site. I can use $form_state['values']['keyword'] in MYMODULE_form_submit() but not in MYMODULE_form_page(). How can I achieve this?

Also ask

We use cookies to deliver the best possible experience on our website. By continuing to use this site, accepting or closing this box, you consent to our use of cookies. To learn more, visit our privacy policy.