I have built a multistep webform using webform version 6.2.2 and Drupal 10 and I want to show a summary element on each step that updates with the information of user input from all previous pages.

The summary element is a processed text/HTML element that can be either a single field outside the step wrapper or separate fields inside each step.

What I have tried so far is altering the element in the form validate callback like this:

function THEME_multistep_validate(&$form, \Drupal\Core\Form\FormStateInterface 
 if ($form['progress']['#current_page'] == "step_2") {
  $form['elements']['step_2']['summary']['#text'] = '<h2>STEP 1 complete</h2>';

As well as in the wizard_next form action:

function THEME_multistep_step_submit(&$form, \Drupal\Core\Form\FormStateInterface  &$form_state)
   $form['elements']['step_2']['summary']['#text'] = '<h2>STEP 1 complete</h2>';


added in the form_alter hook like this:

  array_unshift($form['actions']['wizard_next']['#submit'], 'THEME_multistep_step_submit');

In both ways, the form handlers are called and the $form array reflects the changes but the element is still rendered with the initial value and not updated, regardless if the element is outside or inside the steps/pages of the form. Am I missing something here or is there a better approach for this? Any pointers would be greatly appreciated!

Edit: I found this question about a similar problem: https://stackoverflow.com/questions/54582371/drupal-8-webform-how-to-display-text-input-on-one-page-on-the-next-page but the solution is for changing values of actual input fields, wheareas I am trying to change content of a text/HTML element added via the webform UI.

  • Did you try hook_form_alter the hooks you used just for validation and submit, if you want to alter elements of the form you need hook form alter
    – berramou
    May 13 at 14:15
  • Yes I added the custom handler functions inside the form_alter hook in both cases and they are executed and alter the $form object but the element is not rendered with the updated values.
    – Jamesbeat
    May 13 at 21:25

2 Answers 2


The alter of the processed text/HTML element is a little bit tricky because it doesn't go through the same process as the other elements.

You can see more information here: https://git.drupalcode.org/project/webform/-/blob/6.2.x/src/Plugin/WebformElement/ProcessedText.php

So to alter processed text/HTML element you need to make changes in the webform entity elements, like this: I'm not sure if this is the best way to do so but it works and i didn't find another way.

 * Implements hook_form_alter().
function [MODULE_NAME]_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form_id === "YOU_FORM_ID") {
    /** @var \Drupal\webform\WebformSubmissionInterface $webform_submission */
    $webform_submission = $form_state->getFormObject()->getEntity();
    /** @var \Drupal\webform\Entity\Webform $webform */
    $webform = $webform_submission->getWebform();
    $webform_elements = $webform->getElementsDecoded();
    // Change your processed text here.
    // You can get the submitted values from the previous step.
    // This is the case were the element is part of the step.
    $webform_elements['step_2']['summary']['#text'] = 'Hello this changed text';

  • Altering the element inside the _form_alter hook works fine if I just set the #text value like this: $form['elements']['summary']['#text']. But I want it to update after each previous/next page change from inside the custom form handler added via $form['actions']['wizard_next']['#submit'][] = '[MODULE_NAME]_custom_multi_page_submit'. Strangely, this works once using your approach, but defaults back to the elements initial value in each of the consecutive page changes. I tried adding $form_state->setRebuild(true); but that didn't change anything.
    – Jamesbeat
    May 17 at 10:25

I finally solved it like this, all inside the form_alter hook:

function [MODULE_NAME]_form_alter(&$form, FormStateInterface $form_state, $form_id) {

  if ($form_id === "YOU_FORM_ID") {

    /* setup summary string */
    $summary_string = "You selected: ";

    /* check if a user input value for field a is present /*
    $field_a = $form_state->getValue("field_a");

    if (!empty($field_a)) {
      /* append to summary string */
      $summary_string = $summary_string.$field_a;

    /* check if a user input value for field b is present /*
    $field_b = $form_state->getValue("field_b");

    if (!empty($field_b)) {
      /* append to summary string */
      $summary_string = $summary_string." and ".$field_b;

    /* update text of summary element with the string */
    $form['elements']['summary']['#text'] = $summary_string;


So there is actually no need for handling this in the validation or the wizard_next action.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.