0

Using a term reference field, I am adding the manufacturer's name to the front of our node titles in views for styling and line breaks between the manufacturer field and the title which is really nice. For the node display titles, I am currently using a block view for the manufacturer's name, and placing it above the page title block in the block layout. This stacks the Manufacturers name above the Node title which i don't really prefer:

Manufacturer
Some Node Title

I would like to add the field_manufacturer field to the node display title as a prefix so that it is inline and not stacked like my example above, and I need to add a class to it so that I can target and style it. I am not sure which twig file is responsible for rendering the title, so I would really appreciate help marking this up properly.

Thanks!

2
  • 1
    Do you want to add field_manufacturer` to the title in all views (teaser, full page, etc), or just certain views? I'm not 100% sure but... To change the title on the node's full page view, you can implement template_preprocess_page_title(&$variables) and change $variables['title']. The template file for theming the page title is page-title.html.twig. To change the title field in a view like the teaser, I think you would implement template_preprocess_node(&$variables), and change $variables['label']. In this case, the template file would be node.html.twig. Nov 21, 2019 at 5:40
  • I am looking to change the node title on the default node display. Could you explain "To change the title on the node's full page view, you can implement template_preprocess_page_title(&$variables) and change $variables['title']. " in more detail? Nov 22, 2019 at 3:25

2 Answers 2

2

Posting this answer to help those trying to accomplish the same thing. I was told the code above had security vulnerabilities (which has since been removed see comments below). On the Drupal Slack channel, someone pointed out the following concern with runwithscissors' answer:

"This code is potentially dangerous:$variables['title'] = \Drupal\Core\Render\Markup::create($new_title); A user could set <script>alert("foo")</script> as the Node or Term title and potentially execute code on the site. Typically you don’t want to ever create Markup objects manually. For what you’re doing, I’d suggest setting $term_name to a new key in $variables, then forming your combined title in the Twig template like {{ term_name}} {{ title }}"

So what i ended up doing was adding this template_preprocess_page_title to my MY_SITE.theme file.

(Note: field_manufacturer is the specific field for my use case, so you would need to change all instances of that to your taxonomy reference field name.)

/* Add field_manufacturer to all node titles with field_manufacturer and not empty */
function template_preprocess_page_title(&$variables) {
   $node = \Drupal::request()->attributes->get('node');
   if ($node && $node->hasField('field_manufacturer') && !$node->field_manufacturer->isEmpty()) {
     $term = \Drupal\taxonomy\Entity\Term::load($node->get('field_manufacturer')->target_id);
     $term_name = $term->getName();
     $variables['term_name'] = $term->getName();
   }
 }

This applies to all nodes with the field_manufacturer, but also checks that the term field is NOT empty with && !$node->field_manufacturer->isEmpty()). This was critical as the reference field was not required, so nodes that had the field but didn't have a value crashed the site with Error: Call to a member function getName() on null in template_preprocess_page_title()

Then I copied and overwrote the page-title.html.twig file from my bootstrap base theme which originally renders the title like this:

{% if title %}
  <h1{{ title_attributes.addClass('page-header') }}>{{ title }}</h1>
{% endif %}

And changed the H1 title line to this:

{% if title %}
  <h1{{ title_attributes.addClass('page-header') }}>
    {% if term_name %}
      <span class="MY-DESIRED-CLASS-NAME">{{ term_name }}</span>
    {% endif %}
  {{ title }}</h1>
{% endif %}

This adds a MY-DESIRED-CLASS-NAME span class to the term_name. Also by putting it within {% if term_name %}/{% endif %} statement, it prevents that class from being rendered in the html where there is no term_name present.

Hope this helps someone!

2
  • 1
    Thanks for the thought, but don't worry about removing your up-vote from my answer. I set the title of a node to <script>alert("foo")</script> and confirmed that using Markup::create() will cause the script to execute. I also now realize that the span elements should be added in the template and not the theme. When I searched for how to do the same thing you wanted, I came across many blog posts and up-voted answers using the Markup::create() method. It's clear that no one should do it that way. I deleted my post so no one else makes the same mistake I did, and up-voted your answer. Nov 26, 2019 at 15:31
  • Cool. Thanks! Answer edited for clarity. Nov 26, 2019 at 15:41
0

Would you want to use Automatic Entity Label to actually change the title?

1
  • 1
    No, I keep the manufacturer separate for line breaks and styling in views displays. Nov 22, 2019 at 0:09

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.