1

I am new to Drupal 8 theming and I've been long time trying the following:

I want to add classes to page-title in the template, page-title.html.twig. Two new classes:

1.- 'page_title'

2.- The real title of the page

The code I'm using is,:

{{ title_prefix }}

{%
set classes = [
'page-title',
title|clean_class
]
%}

{% if title %}
<h1{{ title_attributes.addClass( classes ) }}>{{ title }}</h1>
{% endif %}

{{ title_suffix }}

it renders:

<h1 class="js-quickedit-page-title page-title array">FORMACIÓN: CURSOS Y  TALLERES</h1>

The string 'page-title' is working well but the variable title provoke an error:

Notice: Array to string conversion in Drupal\Component\Utility\Html::getClass() (line 72 of core\lib\Drupal\Component\Utility\Html.php).

And print the class, array.

Any help?

1 Answer 1

3

Seems title is a render array. You probably have to use title.value instead. But I'd recommend to simply preprocess that and leave the templates untouched.

You can implement hook_preprocess_hook and then use TitleResolver::getTitle and Html::cleanCssIdentifier to do what you want from inside your theme's *.theme file or from within a custom module's *.module file:

/**
 * Implements hook_preprocess_HOOK().
 */
function MYTHEME/MYMODULE_preprocess_page_title(&$variables) {

  // This won't work properly with Twig debugging enabled.
  // $title = $variables['title'];

  // Here is a safer method to get the current title.
  $request = \Drupal::request();
  $route_match = \Drupal::routeMatch();
  $title = \Drupal::service('title_resolver')->getTitle($request, $route_match->getRouteObject());

  $css_title = \Drupal\Component\Utility\Html::cleanCssIdentifier($title);
  $variables['title_attributes']['class'][] = 'page-title';
  $variables['title_attributes']['class'][] = strtolower($css_title);
}

You can use nearly the exact same snippet to add that CSS class to the <body> tag:

/**
 * Implements hook_preprocess_HOOK().
 */
function MYTHEME/MYMODULE_preprocess_html(&$variables) {

  $request = \Drupal::request();
  $route_match = \Drupal::routeMatch();
  $title = \Drupal::service('title_resolver')->getTitle($request, $route_match->getRouteObject());

  $css_title = \Drupal\Component\Utility\Html::cleanCssIdentifier($title);
  $variables['attributes']['class'][] = strtolower($css_title);
}
4
  • So, I implemented that function, but I'm getting errors when there is no page title available. Any adjustments that you'd recommend?
    – Kellen
    Commented May 5, 2020 at 19:30
  • @Kellen – Depends on the errors and what pages exactly but I'd probably start with some basic if-else to catch that and provide a fallback?!
    – leymannx
    Commented May 5, 2020 at 20:57
  • I'm not much of a programmer. I wouldn't know exactly what kind of if statement to apply. I expanded on my issue here if you can help: drupal.stackexchange.com/questions/293487/… Thank you!
    – Kellen
    Commented May 7, 2020 at 13:50
  • @Kellen – "Expects string but array given" says all. Then you only add the CSS class if (!is_array($title)) { and check on } else { what exactly is inside this array. Maybe the title then is inside $title['value']. You could install the Devel submodule Kint. And then do ksm($title). Flush cache, flush cache and then you get the title variable pretty-printed on your page and you can inspect it.
    – leymannx
    Commented May 7, 2020 at 14:25

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.