Using Drupal::routeMatch() to add node and paragraphs values to the body class using an HTML preprocess function

Published Jul 12, 2022
Updated Jul 12, 2022
By Simon

You may have read my article on how to add a paragraph value to your HTML template using a Drupal static function. Even though it works (and whatever your thoughts are about using static functions as a design pattern), it has been decided that the Drupal static function will be deprecated so we need another solution.

After a bit of further research and a hint from a co-worker, I was introduced to the Drupal routematch service. We can add the same value from our node entity reference revisions paragraphs field using routematch directly to our HTML preprocess function by first checking if the current page is a node.

How do we use the routematch service?

We do this by checking if the current route has the node parameter passed in. If it does, you then have access to all the node object values and can dig deeper. The below code can be added to the HTML preprocess function.

if($node = \Drupal::routeMatch()->getParameter('node')) {
  //Add your code here you want to run if the route is a node
}

From the previous article, where we used the Drupal static function, you will remember that we had to add the page node type class to the CSS selector rule to make sure that our styling was only applied to the node pages. However, if we wrap our static variable in our new block of code then we don't need to use the page-node-type-TYPE_MACHINE_NAME class in our CSS selector rule. Following is our line of code that sets our theme_style variable wrapped in the routematch condition from above.

if($node = \Drupal::routeMatch()->getParameter('node')) {
  $variables['theme_style'] = _myTheme_var('my_var');
}

We can also check if the particular node is of the specific type as we did in our node preprocess function. If the page we are on is a node and of the node type we want, then we have even more control over what pages the class is added to.

You may now think if I can do this then why can't I add the code from the node preprocess function to the HTML preprocess function and be done with the Drupal static function? Well, you would be right in asking and that is what we are going to do.

Since we already have our code from our node pre-process function, we can copy that into our routematch function and then set the value to our attribute instead of setting the Drupal static function value. Below is our final code.

/**
 * Implements hook_preprocess_HOOK() for HTML document templates.
 *
 */
function kodomo_preprocess_html(&$variables)
{
  if($node = \Drupal::routeMatch()->getParameter('node')) {
    
    switch ($node->getType()) {

      // case 'Single Page App - spa':
      case 'spa':

        if (!isset($node->field_content)) { break; }
       
        if (isset($node->field_content)) {
          $paragraphs = $node->field_content;

          $paragraphEntity = $paragraphs->first('target_id')->getValue();
        
          $paragraph = Paragraph::load($paragraphEntity['target_id']);
          
          if (isset($paragraph->field_number_style->value)) {
            $tsValue = 'banner-style-' . $paragraph->field_number_style->value;
            $variables['theme_style'] = $tsValue;
          }
        }

        break;

    }
  }
}

If you would like more explanation for the above code you can get more details in the previous article.

Remember, you also need to add the value to the HTML template twig class function so that it is added to the body class attribute. I've repeat the code below that needs to go in you HTML twig template file to set the body_classes.

{%
  set body_classes = [
    logged_in ? 'user-logged-in',
    not root_path ? 'path-frontpage' : 'path-' ~ root_path|clean_class,
    node_type ? 'page-node-type-' ~ node_type|clean_class,
    db_offline ? 'db-offline',
    theme_style
  ]
%}

 

That's it you can now style your pages using the body class, meaning pages can have totally different looks and can easily be set by the content creator.

That's it for this Druppit. If front-end development and design is your thing, sign up for the newsletter where I share snippets and insights to 20 years of web development, design, and marketing. Until next time, Carpe diem, Bye for now!