English version was created automatically using Drupal module auto_node_translate and free DeepL translator.

How to display the selected content type using a different theme layout

zveřejněno 2022-05-12

In Drupal, you can choose two themes as standard - a default theme for the front-end, and usually another theme for administration. But what if you need to display the selected content type using the admin theme?

For one project, I decided to create the documentation for the site directly as a web page. I created special content type guidelines for it, defined accesses, URLs, menus ... But since the content is "administration" pages, I wanted to display it using admin theme.

For Drupal 7 there was ThemeKey module https://www.drupal.org/project/themekey or Content Theme https://www.drupal.org/project/content_theme. For Drupal 8+, there is the Administration theme https://www.drupal.org/project/admin_theme module, which allows you to use an admin theme based on the URL. But if we want to define a different theme based on the content type, we have no choice but to go into the coding.

UPDATE #1

Finally, I still found the Theme Switcher Rules https://www.drupal.org/project/theme_switcher module, which can change the theme based on the content type exactly. And not only that, there are many more appearance conditions that can be defined. Which might just be a downside - why get a cannon if you only want to get sparrows.

Theme Switcher Rules

 

UPDATE #2

There are two other modules that might be useful.

The first is Theme Negotiation by Rules https://www.drupal.org/project/theme_rule. This is virtually identical to the previous Theme Switcher Rules module. Its rules can be set in the Appearance section.

Theme Negotiation by Rules

The second module is Switch Page Theme https://www.drupal.org/project/switch_page_theme. This one has fewer conditions where the rule applies. But in turn, it allows the rule to be applied when the defined key is used in the URL.

Switch page theme

 

Where to actually change the appearance theme - RouteSubscriberBase?

If I were creating custom pages using code as well, the _admin_route option can be defined in the routing.yml file as part of the route definition: TRUE . So I tried first creating a custom class for RouteSubscriberBase in the src/Routing/RouteSubscriber.php file.

RouteSubscriber alterRoutes

But it doesn't work like that.

The problem is that alterRoutes is only called when the cache is emptied, and also that at this point $node = \Drupal::routeMatch()->getParameter('node'); doesn't work, you can't get the node information here.

Correct place - ThemeNegotiatorInterface

Since Drupal 8, changing the theme appearance is done using theme negotiators, see. " 'theme callback' and hook_custom_theme() replaced by theme negotiators" https://www.drupal.org/node/2158619.

Now that we know where the theme change happens, the rest is easy.

First we define a new service, add services to my_module.services.yml file:

services:
  theme.negotiator.theme_switcher:
   class: Drupal\my_module\Theme\SwitcherNegotiator
   tags:
    - { name: theme_negotiator, priority: -10 }

And in the src/Theme/ SwitcherNegotiator file itself.php we have

/**
 * @file
 * Contains \Drupal\myesi_alter_routes\Theme\SwitcherNegotiator
 */

namespace Drupal\Module\Theme;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Theme\NegotiatorInterface;
class SwitcherNegotiator implements ThemeNegotiatorInterface
{
    /**
     {@inheritdoc}
    */
   public function applies(RouteMatchInterface $route_match)
  {
   use this theme on a certain route.
      $node = $route_match- getParameter('node');
       if ( ! is_null($node)  $node instanceof \Drupal\node\Entity\Node) {
       if ($node- getType() == 'guideline') {
          return true;
     default theme
    return false;
  }
    /**
    * {@inheritdoc}
   */
   public function determineActiveTheme(RouteMatchInterface $route_match)
   {
       // Here you return the actual theme name.
      return 'seven';
    }
}

As you can see, in the SwitcherNegotiator class, it is no longer a problem to get information about the current node. And then apply the theme change just by e.g. content type.

 

Conclusion

If we want to display selected nodes using a different than default theme appearance, we need to create our own theme negotiator. Fortunately, it's not that complicated. If our condition is content type, it's really very simple.

We'll show you how to do something similar for specific nodes some other time.