Include method of adding source entity in getStorage('webform')->create()

Created on 6 March 2025, about 1 month ago

Problem/Motivation

Question:
Is it possible to define the "source entity" for a webform when using entityTypeManager() to create() a webform programatically?

I am using a form that is rendered multiple times on a page, so I need each form to have a source entity so as to apply unique form_wrapper_id's, form_id's, etc. I am constructing and attaching the form using the following code:

function hook_entity_load($entities) {
  foreach ($entities as $entity) { 
    // Build webform
    $webform = \Drupal::entityTypeManager()->getStorage('webform')->create([
      'id' => '<webform_id>',
      'entity_type' => '<entity_type>', // Does not populate source entity
      'entity_id' => '<entity_id>',  // Does not populate source entity
    ]);

    // Create render view to attach
    $renderWebform = \Drupal::entityTypeManager()->getViewBuilder('webform')->view($webform);

    // Attach to entity to render via twig template
    $entity->webform = $renderWebform;
  }
}

I have tried a few different variations on the above in an attempt to pass the source entity to the built form with no luck. Even without the source entity the forms do submit and the Ajax does work, but because they don't have source entities, all forms on the page get updated with replace commands and logic is applied indiscriminately. Wouldn't be a problem if the form was only rendered once, but becomes an issue since there are multiple of the same form on the page.

Is there a way to set the source entity when using entityTypeManager() to create() a webform in a hook?

Context and Alternatives Attempted

Normally I would use a render array in a twig template to pass a source entity, like the code below

{{ 
  { 
    '#type': 'webform', 
    '#webform': '<webform_id>', 
    '#entity_type': '<type>', 
    '#entity_id': <id>,  
  } 
}}

The render array does set the source entity ( as the docs suggest ), however my particular setup breaks the Ajax behavior of forms rendered using a render array. I am using...

  1. A view which is loaded via Ajax
  2. An entity type rendered multiple times in that view, once per row
  3. A copy of the form attached to each of those entities rendered by the view

This setup breaks Ajax submission for the render array form, but not forms generated via entityTypeManager() or loaded via a block. I've attempted to restore the appropriate uniqueness and Ajax behaviors by...

  • Loading a block of the webform via entityTypeManager() - (also no source entity)
  • Loading a block of the webform using twig tweaks, i.e. {{ drupal_entity('block','<block_id>') }} - (also no source entity)
  • Following the instructions in this stackexchange answer to set the webform url
  • Hook altering the ['#action'] value
  • Hook altering the form id's

For all of the above either the AJax fails or the forms conflict due to a lack of supplied source entity.

Steps to reproduce

  1. Create a few entities
  2. Create a view rendering a list of those entities, whole thing not fields
  3. Create a form that has Ajax turned on, and uses some conditions for element visibilty
  4. Add that form to the entity with code like above in hook__load
  5. Load view on a page via Ajax (admittedly this part is also complex)
  6. Submit form, see all forms update

Inspecting the rendered HTML will also show that the multiple rendered forms do not have the appropriately "source entity" altered IDs and conditional logic. I believe the simplest solution is to find a way to pass the source entity, but perhaps there is some alternative solution that would get the Ajax behaviors resolved for a render array.

💬 Support request
Status

Active

Version

6.3

Component

Documentation

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Production build 0.71.5 2024