Score:1

How to prevent theme change caused by $rendererService->renderPlain()

ru flag

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.

4uk4 avatar
cn flag
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 https://drupal.stackexchange.com/questions/281447/themenegotiator-not-working-for-admin-pages
Score:1
ru flag

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.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.