1

I'm trying to re-use the output from a heavily customized field formatter as <select><option> text in a Webform. I managed to re-use field display, but it has the side-effect of switching the theme used for rendering.

Below is a simplified code, the lines $dateRenderArray = ... and $dateHtml = ... are original and cause the problem:

function mymodule_webform_options_alter(array &$options, array &$element, $options_id = NULL) {
  foreach ($options as $value => $text) {
    $entity = getEntityByOption($value);

    //reuse custom field formatter output
    $dateRenderArray = $entity->get('field_daterange')->view('teaser');

    //the following line causes the theme change
    $dateHtml = \Drupal::service('renderer')->renderPlain($dateRenderArray);

    $datePlaintext = str_replace(["\n", "&nbsp;"], ["", " "], trim(strip_tags($dateHtml)));
    $muchBetterOptionText = $someOtherPlaintextFromEntity . '  ' . $datePlaintext;
    $options[$value] = $muchBetterOptionText;
  }
}

This works excellent in the frontend form, for the submission emails and also in the admin webform submission list.

But in a single webform submission detail view, those lines cause an unwanted theme change from admin theme to frontend theme.

Question:
How can I prevent the theme change from renderPlain() and keep the admin theme when viewing a single webform submission?

Optional bonus question:
Why does my hook work correctly in the webform submission list and not in webform submission detail view? The submission list uses exactly the same function, it renders the same processed option text in the corresponding column, but I do correctly stay inside the admin theme when viewing the list. But only in the detail view switches to the frontend theme.

1
  • Normally there is no theme switching within a request. The theme is negotiated globally for the entire request. My guess would be there are two requests, one rendering the content and one invoking the hook. Can you check the route names for both? If you have two different routes then check for each the requirements for negotiating the admin theme. If necessary implement your own negiotiator for the second request. See drupal.stackexchange.com/questions/281447/…
    – 4k4
    Jul 21 '21 at 19:29
1

Found out there is some very Webform-specific logic involved (@see WebformSubmission entity using a custom theme and render logic).

My custom rendering is confusing webform's logic. I switched to Webform's own renderer, and enforced the admin theme after my custom rendering.

function mymodule_webform_options_alter(array &$options, array &$element, $options_id = NULL) {
  //webform's own rendering service
  $webformRenderer = \Drupal::service('webform.theme_manager');

  foreach ($options as $value => $text) {
    $entity = getEntityByOption($value);

    //reuse custom field formatter output
    $dateRenderArray = $entity->get('field_daterange')->view('teaser');

    //the following line causes a theme change on route entity.webform_submission.canonical
    $dateHtml = $webformRenderer->renderPlain($dateRenderArray);

    $datePlaintext = str_replace(["\n", "&nbsp;"], ["", " "], trim(strip_tags($dateHtml)));
    $muchBetterOptionText = $someOtherPlaintextFromEntity . '  ' . $datePlaintext;
    $options[$value] = $muchBetterOptionText;
  }

  //route name is null, must use request instead
  if (strpos(\Drupal::request()->getRequestUri(), '/admin/structure/webform/manage/MY_WEBFORM_ID/submission/') === 0) {
    //only admins can view webform submissions
    $webformRenderer->setCurrentTheme(\Drupal::config('system.theme')->get('admin'));
  }
}

Looks a bit hacky, but it does the trick.

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.