2

I have a Drupal 8 site with a content type called Landing Page. I'm using the bootstrap theme and I have the block showing the brand info (including site slogan) in the navbar.

I want some of the landing pages to have a different site slogan (shown in the navbar). How can I do that?

What I tried

I thought of adding a text field custom site slogan to my Landing Page content type and then using a twig template (content type node template) to show the slogan, but the slogan is printed in the header, and the template comes after that.

I could also make a different branding block for each page I need to change the slogan on and manually change the text in a twig template, but that seems like a very horrible, labor intensive way to do it.

  • Agree having a field on the content type to override the slogan text, then use preprocess_node() to check if the field has value and replace the slogan from the site block. Or if the alternate slogan is the same for all changed pages, use a boolean field on the content type? Off the top of my head, seems like you'll need some flag somewhere on the content type level... – Prestosaurus Jan 28 at 16:10
  • Further, if you do make a field on the content type, I would suggest a select field that can be reused and updated. Have a default slogan, then a list of alternatives. This field could then be reused with its logic on any node. Just to future proof if you're going to do all that work. – Prestosaurus Jan 28 at 16:31
  • 4
    You could use HOOK_preprocess_block and in there check for node pages with $node = \Drupal::routeMatch()->getParameter('node'); – Hudri Jan 28 at 17:59
  • Could \Drupal::routeMatch()->getParameter('node'); be translated in OOP to 50 out of 500 nodes? – Prestosaurus Jan 28 at 20:03
2

Ok, thanks to the hint from @Hudri, here's what I did.

In mycustomtheme.theme:

function MYCUSTOMTHEME_preprocess_block(&$vars) {
  if ($vars['configuration']['id'] === 'MYMODULE_site_branding_nolinks_block') {
    $site_config = \Drupal::config('system.site');
    $vars['site_slogan'] = $site_config->get('slogan');
    $vars['site_name'] = $site_config->get('name');
    $node = \Drupal::routeMatch()->getParameter('node');
    if ($node instanceof \Drupal\node\NodeInterface) {
      $type = $node->getType();
      // For landing pages, set the site slogan to the value of the slogan field.
      if ($type === 'landingpage') {
        $node = \Drupal::entityTypeManager()->getStorage('node')->load($node->id());
        $slogan_field = $node->get('field_slogan')->getValue();
        $slogan_field = $slogan_field[0]['value'];
        $vars['site_slogan'] = $slogan_field;
      }
    }
  }
}

But, we're not done yet, because the block (provided by my custom module) is cached the same for every page; it needs to be cached per URL, since it might be different for each landing page.

To fix that, in mymodule/src/Plugins/Blocks/myBlock.php, add this code:

  // Caching must be added here:
  // https://drupal.stackexchange.com/questions/223376/what-is-the-correct-way-to-set-cache-contexts-on-custom-blocks
  public function getCacheContexts() {
    return Cache::mergeContexts(parent::getCacheContexts(), ['url.path', 'url.query_args']);
  }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.