Broken title in modal dialog when title is a render array

Created on 5 February 2016, almost 9 years ago
Updated 24 April 2023, over 1 year ago

Problem/Motivation

When opening a view in a modal dialog, the title says 'Array' text as this title is set as a render array then casted to a string instead by being rendered by PHP code.

Any render array title passed to a Drupal dialog is also impacted including off canvas dialog.

Steps to reproduce

  1. Install Drupal using standard profile
  2. Edit the Content view (/admin/structure/views/view/content)
  3. Add a "Custom text" field to thw view with content:
    {{ attach_library('core/drupal.dialog.ajax') }}
    <p><a class="use-ajax" data-dialog-type="modal" href="/admin/content">Content</a></p>
    
  4. View the content view page and click the custom text link

This will cause the title of the modal to be 'Array' and will produce a warning log message:

Warning: Array to string conversion in Drupal\Component\Render\PlainTextOutput::renderFromHtml() (line 22 of /var/www/html/web/core/lib/Drupal/Component/Render/PlainTextOutput.php)

Image of issue:

Proposed resolution

Allow $title to be a render array in addition to a string in the Drupal dialog system. If a render array is passed, render it, and attach any libraries and drupalSettings as required.

Image when fixed:

Remaining tasks

Consider removing title asset attachment support, if warranted, in follow up ticket as per comment #2663316-65: Broken title in modal dialog when title is a render array โ†’ .
Current suggested scope is getting views support working without changing views code. Also has benefit allowing extra HTML in the dialog title and different dialogs in the future could also take advantage of this.

Consider removing render array support for title asset, if warranted, in follow up ticket as per comment #2663316-79: Broken title in modal dialog when title is a render array โ†’ .

User interface changes

N/A

API changes

Allow $title to be an string or an render array in the Drupal dialog system.

Data model changes

N/A

Release notes snippet

N/A

Workaround

Until such issue is fixed, a workaround is possible in a module or theme.

// foo.module or foo.theme

use Drupal\foo\Render\Element\MyViewElement;

/**
 * Implements hook_element_info_alter().
 */
function foo_element_info_alter(&$types) {
  if (isset($types['view'])) {
    $types['view']['#pre_render'] = $types['view']['#pre_render'] ?? [];
    // Fix title is an array in dialogs, remove when fixed.
    // @see https://www.drupal.org/project/drupal/issues/2663316
    $types['view']['#pre_render'][] = MyViewElement::class . '::preRender';
  }
}

// [module or theme]/src/Render/Element/MyViewElement.php

namespace Drupal\foo\Render\Element;

use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Render\Element\RenderCallbackInterface;

/**
 * MyViewElement helper class.
 */
class MyViewElement implements RenderCallbackInterface {

  /**
   * Fix title is an array in dialogs. Remove when fixed.
   *
   * @see https://www.drupal.org/project/drupal/issues/2663316
   */
  public static function preRender($element) {
    if (isset($element['#title']) && is_array($element['#title'])) {
      // Apply attachments such as drupalSettings and libraries.
      BubbleableMetadata::createFromRenderArray($element)
        ->merge(BubbleableMetadata::createFromRenderArray($element['#title']))
        ->applyTo($element);
      // Render to string.
      $element['#title'] = \Drupal::service('renderer')->renderPlain($title_array);
    }
    return $element;
  }

}
<!-- Old image for [object][oject] <img src="/files/issues/Broken%20view%20title%20in%20modal%20dialog.png" width="500" alt="" /> -->
๐Ÿ› Bug report
Status

Needs work

Version

10.1 โœจ

Component
Ajaxย  โ†’

Last updated about 9 hours ago

Created by

๐Ÿ‡ฉ๐Ÿ‡ชGermany juliaschwarz

Live updates comments and jobs are added and updated live.
  • Needs issue summary update

    Issue summaries save everyone time if they are kept up-to-date. See Update issue summary task instructions.

  • Needs screenshots

    The change alters the user interface, so before and after screenshots should be added to document the UI change. Make sure to capture the relevant region only. Use a tool such as Aviary on Windows or Skitch on Mac OS X.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • ๐Ÿ‡ธ๐Ÿ‡ฐSlovakia coaston

    Guys, is that project dead already ? ....will that patch #76 work also on D10 ?

  • ๐Ÿ‡ต๐Ÿ‡ฑPoland lamp5 Rzeszow

    Yesss, Drupal is dead....

  • ๐Ÿ‡ฆ๐Ÿ‡บAustralia silverham

    Attaching draft patch for Drupal test system without attachments.

  • Status changed to Needs review over 1 year ago
  • last update over 1 year ago
    29,357 pass, 2 fail
  • ๐Ÿ‡ฆ๐Ÿ‡บAustralia silverham

    Trying to trigger test system.

  • Status changed to Needs work over 1 year ago
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia shashank5563 New Delhi

    Create a new patch for this issue. This patch issue fixed on my local.

    I have tested for view content and node edit link found it is working fine.

  • last update over 1 year ago
    Custom Commands Failed
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia shashank5563 New Delhi
  • last update over 1 year ago
    29,388 pass
  • Status changed to Needs review over 1 year ago
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia shashank5563 New Delhi
  • Status changed to Needs work over 1 year ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States smustgrave

    Was previously tagged for issue summary update, which may be good but should be verified.

    But as a bug it will need a test case showing the issue.

    Thanks

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia omkar.podey

    omkar.podey โ†’ made their first commit to this issueโ€™s fork.

  • First commit to issue fork.
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia sakthi_dev

    Created a MR with rerolled against 11.x. Please someone address the comment #107.

  • Pipeline finished with Failed
    10 months ago
    Total: 555s
    #93675
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia djsagar

    Steps to reproduce
    1. Install Drupal using standard profile
    2. Edit the Content view (/admin/structure/views/view/content)
    3. Add a "Custom text" field to thw view with content:

    {{ attach_library('core/drupal.dialog.ajax') }}
    <p><a class="use-ajax" data-dialog-type="modal" href="/admin/content">Content</a></p>

    4. View the content view page and click the custom text link
    This will cause the title of the modal to be 'Array' and will produce a warning log message:

    Before applied MR, for the Warning in logs:
    Warning: Array to string conversion in Drupal\Component\Render\PlainTextOutput::renderFromHtml() (line 22 of /app/core/lib/Drupal/Component/Render/PlainTextOutput.php)

    Tested MR !6569, After applied MR Warning messages is no longer coming in logs.

    Need to fix pipeline, so not updating status.

  • Pipeline finished with Failed
    10 months ago
    Total: 231s
    #93727
  • Pipeline finished with Success
    10 months ago
    Total: 562s
    #93730
  • Pipeline finished with Canceled
    10 months ago
    Total: 168s
    #93755
  • Status changed to Needs review 10 months ago
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia djsagar

    pipeline issue fixed moving NR.

  • Pipeline finished with Failed
    10 months ago
    Total: 859s
    #93758
  • Pipeline finished with Failed
    10 months ago
    Total: 469s
    #93801
  • Pipeline finished with Failed
    10 months ago
    Total: 568s
    #93854
  • Pipeline finished with Failed
    10 months ago
    Total: 566s
    #93885
  • Pipeline finished with Failed
    10 months ago
    Total: 465s
    #93967
  • Pipeline finished with Failed
    10 months ago
    Total: 485s
    #93999
  • Status changed to Needs work 10 months ago
  • Pipeline finished with Failed
    10 months ago
    Total: 173s
    #95586
  • Pipeline finished with Canceled
    10 months ago
    Total: 186s
    #95678
  • Pipeline finished with Success
    10 months ago
    Total: 480s
    #95681
  • Status changed to Needs review 10 months ago
  • Pipeline finished with Failed
    10 months ago
    Total: 519s
    #96929
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States smustgrave

    Hiding patches for clarity.

    Appears issue summary and screenshots were added in #93 so removing those tags

    Ran test-only feature so removing that tag too

    1) Drupal\Tests\views\FunctionalJavascript\Plugin\views\Handler\FieldTest::testModalDialogTitle
    Failed asserting that two strings are equal.
    --- Expected
    +++ Actual
    @@ @@
    -'Content'
    +'Array'
    /builds/issue/drupal-2663316/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php:94
    /builds/issue/drupal-2663316/core/modules/views/tests/src/FunctionalJavascript/Plugin/views/Handler/FieldTest.php:112
    /builds/issue/drupal-2663316/vendor/phpunit/phpunit/src/Framework/TestResult.php:728
    

    Reviewing the code the check for array makes sense.

    Looking at the remaining tasks seems there's still decisions to be made or follow ups created

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia omkar.podey

    omkar.podey โ†’ changed the visibility of the branch 2663316-broken-title-in to hidden.

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia omkar.podey

    omkar.podey โ†’ changed the visibility of the branch 2663316-broken-title-in to active.

  • Status changed to Needs work 10 months ago
  • ๐Ÿ‡ซ๐Ÿ‡ฎFinland lauriii Finland

    It doesn't look like the MR is implementing the feedback from #97.

  • Pipeline finished with Failed
    10 months ago
    Total: 178s
    #100452
  • Pipeline finished with Running
    10 months ago
    #100499
  • Pipeline finished with Failed
    10 months ago
    Total: 775s
    #100801
  • Pipeline finished with Failed
    10 months ago
    Total: 485s
    #101206
  • Pipeline finished with Failed
    10 months ago
    Total: 189s
    #101430
  • Pipeline finished with Failed
    10 months ago
    Total: 554s
    #101487
  • Status changed to Needs review 10 months ago
  • Pipeline finished with Success
    10 months ago
    Total: 1278s
    #103779
  • Pipeline finished with Success
    10 months ago
    Total: 560s
    #104882
  • Pipeline finished with Success
    10 months ago
    Total: 659s
    #106159
  • Pipeline finished with Canceled
    10 months ago
    Total: 109s
    #106830
  • Pipeline finished with Success
    10 months ago
    Total: 473s
    #106834
  • Pipeline finished with Success
    10 months ago
    Total: 556s
    #107687
  • Status changed to Needs work 10 months ago
  • The Needs Review Queue Bot โ†’ tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

    This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

    Consult the Drupal Contributor Guide โ†’ to find step-by-step guides for working with issues.

  • Pipeline finished with Failed
    10 months ago
    Total: 185s
    #111521
  • Pipeline finished with Success
    10 months ago
    Total: 486s
    #111591
  • Status changed to Needs review 10 months ago
  • Pipeline finished with Success
    10 months ago
    Total: 482s
    #113427
  • Status changed to RTBC 10 months ago
  • ๐Ÿ‡ซ๐Ÿ‡ฎFinland lauriii Finland

    The solution looks, although I realized there isn't a perfect solution available to this because people may still continue using render arrays for #title. I think what's here is fine for now and we can revisit this later in case that we find a dialog solution that supports markup for the title.

  • Pipeline finished with Success
    10 months ago
    Total: 482s
    #113625
  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom alexpott ๐Ÿ‡ช๐Ÿ‡บ๐ŸŒ

    Discussed with @lauriii we agreed that the common code in DialogRenderer, ModalRenderer and WideModalRenderer should be refactored into a method so that we don;t repeat ourselves. Also the renderer service is injected so there's no need to do \Drupal::service('renderer')

  • Pipeline finished with Success
    10 months ago
    Total: 550s
    #113654
  • ๐Ÿ‡ซ๐Ÿ‡ฎFinland lauriii Finland

    FWIW, the latest commit looks good ๐Ÿ‘

  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom alexpott ๐Ÿ‡ช๐Ÿ‡บ๐ŸŒ

    Hiding all the patches.

  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom alexpott ๐Ÿ‡ช๐Ÿ‡บ๐ŸŒ

    The deprecation we're adding here is odd... because it is fixing some that is broken only to tell people we're going to break it again. I think that given things are broken if you pass this an array we should add a typehint and be done. Since this is a contructor it does not affect classes in contrib that extend from it.... unless they call parent with $title as an array - and that is broken so already.

  • Pipeline finished with Success
    10 months ago
    Total: 497s
    #114703
  • ๐Ÿ‡ซ๐Ÿ‡ฎFinland lauriii Finland

    I agree that the deprecation approach is a bit strange because it's fixing something to break it later. It tried to optimize to minimize the pain, and I don't think the cost for that was too high. That said, I don't have a strong preference to any particular direction so long as we get the bug fixed. ๐Ÿ˜‡

  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom alexpott ๐Ÿ‡ช๐Ÿ‡บ๐ŸŒ

    Added a CR to inform people about the new helper - https://www.drupal.org/node/3426632 โ†’

  • Pipeline finished with Success
    10 months ago
    Total: 544s
    #114724
  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom alexpott ๐Ÿ‡ช๐Ÿ‡บ๐ŸŒ

    Committed and pushed 4add05d05f to 11.x and 4b835fad4e to 10.3.x. Thanks!

    • alexpott โ†’ committed 4b835fad on 10.3.x
      Issue #2663316 by omkar.podey, jofitz, alexpott, shashank5563, samuel....
  • Status changed to Fixed 9 months ago
  • Automatically closed - issue fixed for 2 weeks with no activity.

  • ๐Ÿ‡ท๐Ÿ‡ธSerbia sakiland

    I'm not sure if this is the right place to put this (the issue is fixed and merged to the 10.3.x and 11.x) or I need to open another bug, but this issue needs more work.

    The fix doesn't check type of the returning value for titleResolver

    $title = $this->titleResolver->getTitle($request, $route_match->getRouteObject())->render();
    

    Function getTitle() can return an array or a string

    <?php
    namespace Drupal\Core\Controller;
    
    interface TitleResolverInterface {
    
      /**
       * Returns a static or dynamic title for the route.
       *
       * @return array|string|\Stringable|null
       *   The title for the route.
       */
      public function getTitle(Request $request, Route $route);
    
    }
    

    This can produce error if some module overwrite this function and return a string. For example, with Webform module I'm getting following error:
    Error: Call to a member function render() on string in Drupal\Core\Render\MainContent\DialogRenderer->getTitleAsStringable() (line 145 of /var/www/html/web/core/lib/Drupal/Core/Render/MainContent/DialogRenderer.php).

    So, we need to put additional check, for example:

      protected function getTitleAsStringable(array $main_content, Request $request, RouteMatchInterface $route_match): \Stringable|string|null {
        $title = NULL;
        if (array_key_exists('#title', $main_content)) {
          if (is_array($main_content['#title'])) {
            $title = $this->renderer->renderInIsolation($main_content['#title']);
          }
          else {
            $title = $main_content['#title'];
          }
        }
        elseif ($titleObj = $this->titleResolver->getTitle($request, $route_match->getRouteObject())) {
          if (is_string($titleObj) || $titleObj instanceof \Stringable) {
            $title = (string) $titleObj;
          }
          else {
            $title = $this->titleResolver->getTitle($request, $route_match->getRouteObject())->render();
          }
        }
        return $title;
      }
    
  • ๐Ÿ‡ท๐Ÿ‡ธSerbia sakiland

    Here's the patch if somebody needed it until final fix.

  • ๐Ÿ‡ท๐Ÿ‡ธSerbia sakiland

    Here's the patch for Drupal 10.2 (this version of Drupal use $this->renderer->renderPlain() instead of $this->renderer->renderInIsolation()

  • ๐Ÿ‡ธ๐Ÿ‡ฐSlovakia coaston

    thank you, it works fine for Drupal 10.2.5

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States bfuzze9898

    I'm seeing this also when rendering a view page in a dialog. Patch #137 worked for me.

  • ๐Ÿ‡จ๐Ÿ‡ญSwitzerland berdir Switzerland

    Seeing fatal errors caused by the problem mentioned in #135 on 10.3.

    @sakiland: The approach to handle such an issue is either to revert the original issue, which would be too complicated at this point or create a follow-up, did that now: ๐Ÿ› DialogRenderer::getTitleAsStringable() does not support all return types of TitleResolverInterface::getTitle() Fixed . Working on a fix for that there.

  • ๐Ÿ‡ธ๐Ÿ‡ฐSlovakia coaston

    @sakiland - thank you for your patch, it looks like it works fine for Drupal 10.2x however only for nodes. When you try patch #137 to render in modal/dialog/off canvas USER, there is an error:

    Error: Call to a member function render() on array in Drupal\Core\Render\MainContent\DialogRenderer->getTitleAsStringable() (line 149 of /core/lib/Drupal/Core/Render/MainContent/DialogRenderer.php).
    
    #0 /core/lib/Drupal/Core/Render/MainContent/OffCanvasRenderer.php(63): Drupal\Core\Render\MainContent\DialogRenderer->getTitleAsStringable()
    #1 /core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php(90): Drupal\Core\Render\MainContent\OffCanvasRenderer->renderResponse()
    #2 [internal function]: Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray()
    #3 /core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(111): call_user_func()
    #4 /vendor/symfony/http-kernel/HttpKernel.php(186): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch()
    #5 /vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\Component\HttpKernel\HttpKernel->handleRaw()
    #6 /core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\Component\HttpKernel\HttpKernel->handle()
    #7 /core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle()
    #8 /core/lib/Drupal/Core/StackMiddleware/ContentLength.php(28): Drupal\Core\StackMiddleware\KernelPreHandle->handle()
    #9 /core/modules/big_pipe/src/StackMiddleware/ContentLength.php(32): Drupal\Core\StackMiddleware\ContentLength->handle()
    #10 /core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\big_pipe\StackMiddleware\ContentLength->handle()
    #11 /core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass()
    #12 /core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle()
    #13 /core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
    #14 /core/lib/Drupal/Core/StackMiddleware/AjaxPageState.php(36): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
    #15 /core/lib/Drupal/Core/StackMiddleware/StackedHttpKernel.php(51): Drupal\Core\StackMiddleware\AjaxPageState->handle()
    #16 /core/lib/Drupal/Core/DrupalKernel.php(704): Drupal\Core\StackMiddleware\StackedHttpKernel->handle()
    #17 /index.php(19): Drupal\Core\DrupalKernel->handle()
    #18 {main}
    
    
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance lazzyvn paris

    why this ticket is fixed. I just try with use-ajax with a simple view, it always shows the table instead of the view title

    I try debug it show $main_content['#title'] have #markup

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States chucksimply

    Assuming this is fixed in 10.3? The original commit in #132 plus the related issue in #135 was committed as well. Good to go?

Production build 0.71.5 2024