8

I need to set a field value as CSS class in a page template. How can I do it the Twig way?

{{attributes.addClass('class-name')}} is the way to set the class manually.

I have a list field to let the user set a background color for a part of the site. In Drupal 7 I used this code.

<div class="<?php print render($content['field_background']); ?>">

In Drupal 8, I can print the field with {{ content.field_background }}, but <div class="{{ content.field_background }}"> doesn't work.

  • There are a number of ways you can do this in the template file with Twig either using the new set classes code, i.e. {% set classes = [ ... and then print the classes as <article{{ attributes.addClass(classes) }}> or you can do something like <div{{ content_attributes.addClass('foobar' | clean_class) }}> as well. As the note above says, I think we need more info. If you want a field value as a class, it would help to use Kint and Twig debug as well and you might need to set a var with a preprocess function but perhaps not necessary. – Danny Englander Mar 9 '16 at 19:17
  • I edited my question. – deelite Mar 9 '16 at 19:59
  • Which template is this, page, node, field? – 4k4 Mar 9 '16 at 20:35
  • Page. The field content I already get with preprocess_page. I think I only need some twig knowledge... – deelite Mar 9 '16 at 20:39
  • What is in the preprocess_page? – 4k4 Mar 9 '16 at 20:45
6

This can be done in a few ways, you can do it all in the node template with Twig or you can create a preprocess function and create a variable for use in the node template. The key to learning what is in the array is to use Devel Kint. Without that, you won't know what is in the array.

First install Kint which comes with the Devel module for Drupal 8. Next, pick your node template (but this can be done in any kind of template) and examine the content variable like so (ideally at the bottom of the template).

{{ kint (content) }}

enter image description here

From this, we get debugging info printed on the page and if you expand the array, you'll see a whole slew of information. Right away, I see my background value and I can construct a path to print this out as

{{ content.field_background[0]['#markup'] }}

Now you can print this as a background style or class in a div

<div style="background-color: {{ '#' }}{{ content.field_background[0]['#markup'] }};" class="color-{{ content.field_background[0]['#markup'] }}">
<h2>Hello</h2>
</div>

I've tested this ands it works great, the div rendered the background color I had selected in my field list on node edit.

Now this is not ideal so we probably want to create a variable for this in a preprocess_node in our theme's .theme file.

function MYTHEME_preprocess_node(&$vars) {
  $vars['bgcolor'] = '#' . $vars['content']['field_background'][0]['#markup'];
}

Now that I have a var created, it's much cleaner to print this out:

 <div style="background-color: {{ bgcolor }};" >
      <h2>Hello</h2>
    </div>

One note for above, you should probably wrap this with an if statement to check if it's empty or not.

This would work or structure the if statement where you like it

   {% if bgcolor %}
    <div style="background-color: {{ bgcolor }};" >
      <h2>Hello</h2>
    </div>
    {% endif %}
3

In a node template the fields are in {{ content }}. In a page template there is no content variable, instead there is a page variable which contains regions {{ page.region }}.

Since you asked about the page template, we can't use content.

But you can use {{ node }} in both templates. The node object is always in a node template and in the page template, when the page is displaying a node.

So this should work in both templates:

<div class="{{ node.field_background.value|clean_class }}">
  • As far as I can tell with tests I ran using Devel Kint, "value" does not work. – Danny Englander Mar 11 '16 at 14:48
  • This is hard to find out with kint(), you will only see a fielditemlist. value gets with some magic of twig and the field object the value of the first item. In a multivalue field you can access any item by inserting a number starting at zero: node.field_myfield.0.value – 4k4 Mar 11 '16 at 16:24

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.