0

I am relatively new to Drupal and have just successfully (thanks to help from this community) pulled out a field value and used it to display a custom icon on the page.

Coming from a HTML/CSS only kind of world, I am finding it hard to understand how to do simple things, such as take variables I've created and insert them within the {{ content }} area.

In my specific application, I have a page that NOW looks like this:

Custom Icon 3, Custom Icon 4, Custom Icon 5

{{ content starts here }}

Node Title

Node Subtitle

Custom Icon 1, Custom Icon 2, Custom Icon 3

Image

(page continues)

{{ content ends here }}

What I'd like to do is have the Custom Icons all in a nice line together beneath the Subtitle, but since the 3, 4, and 5 were generated by code, they're outside the {{ content }} block. Icons 1, 2, and 3 are created by hiding the text value (which is either there or not) and displaying a background image...a totally different method that doesn't work for 4, 5, and 6 because in those cases the value isn't binary, it's got several different values.

I'm not married to any specific method to accomplish this but am curious about how I can "best" make these all line up nicely together, one after another, in that order 1, 2, 3, 4, 5, 6.

I believe it's relatively easy to do it like this:

1, 2, 3, 4, 5, 6

Node Title

Node Subtitle

Image...etc.

But that's not really what I'd like to do. This is how I'd like it:

Node Title

Node Subtitle

1, 2, 3, 4, 5, 6

Image...etc.

This would be relatively easy to do with CSS if I had better access to the inside of the {{ content }} and could make a div, assign it a class, place it in the "4" position, and style it to show as with 1, 2, and 3. But I don't see how to actually accomplish that when the variables are OUTSIDE that immutable {{ content }} block.

I would greatly appreciate someone helping me better understand this process, even if it is to say that I did everything bass-ackward and should simply make these icon fields images and upload the right image into the field each time. I have a site with a large amount of content on it but not so large I couldn't redo this Content Type from scratch the right way. Just seems so strange to me that something so easy to accomplish with a little PHP has been so difficult to get right in this case.

Again, thank you in advance for any and all thoughts. I appreciate your taking the time to offer insight to a relative newbie. I've done CONTENT with Drupal for years, but this is the first time I've been delving deeper into the development side and I am sorry if these come out as very basic questions. Most of the documentation assumes a level of D7 knowledge that I don't have, and the explanations are aimed at people who have been developing D7 sites and need to know the differences, rather than at someone coming in fresh. Or instructions are for D7 entirely.

0

You don't have to use {{ content }} only - this is a variable made up of all the renderable elements in the entity being rendered.

For instance, if you have 4 fields, Field A, Field B, Field C, Field D, you can dictate how/where they are output in the entity template like so, by rendering individually:

<div class="section-main">
  {{ content.field_a }}
  {{ content.field_b }}
</div>

<h4>{{ content.field_c }}</h4>
<p>{{ content.field_d }}</p>

The most common thing most people will encounter in theming will be the theming of fields and entities (like node).

If you wanted the markup within the field, you'd create/edit the appropriate field-- template in your theme and move it there. Lets say you wanted to move the h4 into the Field C template:

field--field-c.html.twig:

{% for item in items %}
  <h4>{{ item.content }}</h4>
{% endfor %}

Now anytime that field is rendered, it is wrapped with an h4 (per value, if it is a multivalue field - check field.html.twig for more info).

Then, back in the node template you remove the h4:

{{ content.field_c }}

The h4 is still in the page, it's just in the field template now. You can break it down any number of ways that is suitable for you.

Let's say you did a mytheme_node_preprocess in your themes mytheme.theme file and created some new variables for the node template. Now that you know how to break down the content variable, you can intersperse custom variables with that:

<h1>{{ title }}</h1>

<h2>{{ content.field_subtitle }}</h2>

{{ custom_var }}

{{ content.field_a }}

<h6>{{ custom_var_2 }}</h6>

{{ content.field_b }}

and so on.

Here is a real example from a project of mine to demonstrate a little further:

node--collection.html.twig

{%
  set classes = [
    'node',
    'node--type-' ~ node.bundle|clean_class,
    node.isPromoted() ? 'node--promoted',
    node.isSticky() ? 'node--sticky',
    not node.isPublished() ? 'node--unpublished',
    view_mode ? 'node--view-mode-' ~ view_mode|clean_class,
    'hl__full-template__page-content',
    'hl__full-template__page-content--full',
    'hl__collection-details'
  ]
%}

<article{{ attributes.addClass(classes) }}>
  {{ title_prefix }}{{ title_suffix }}

  {% if node.field_featured_image %}
    <div class="hl__collection-details__main-image">
      {{ content.field_featured_image }}
    </div>
  {% endif %}

  <section class="hl__rich-text">
    {{ content.body }}
  </section>

  <div class="hl__collection-details__columns">
    <div class="hl__collection-details__divider"></div>
    <div class="hl__collection-details__how-to">
      <section class="hl__rich-text hl__rich-text--small">
        <h2 class="hl__comp-heading">Accessing These Materials</h2>
        {{ content.field_how_to_use }}
      </section>

      {% if view_records %}
        <div class="hl__collection-details__how-to-button">
          {{ view_records }}
        </div>
      {% endif %}
    </div>
    <div class="hl__collection-details__ctas">
      <section class="hl__contact-list">
        <div class="hl__contact-list__container">
          <h2 class="hl__comp-heading ">Contact</h2>
          <div class="hl__contact-list__items">
            <section class="hl__contact-info">
              {% if node.field_contact_person.target_id %}
                {{ content.field_contact_person }}
              {% else %}
                {% include '@mytheme/misc/freeform--contact.html.twig' %}
              {% endif %}
            </section>
          </div>
        </div>
      </section>

      {% if node.field_call_to_action.target_id %}
        {{ content.field_call_to_action }}
      {% endif %}
    </div>
  </div>

  {% if node.field_related_collections.target_id or node.field_related_how_tos.target_id %}
    <hr class="hl__section-divider" />
  {% endif %}

  {% if node.field_related_collections.target_id %}
    <section class="hl__overlay-promo-grid">
      <div class="hl__overlay-promo-grid__container">
        <h2 class="hl__comp-heading hl__comp-heading--left">Related Collections</h2>
        <div class="hl__overlay-promo-grid__grid">
          {{ content.field_related_collections }}
        </div>
        {% if node.field_see_all_collections %}
          <div class="hl__overlay-promo-grid__see-all">
            {{ content.field_see_all_collections }}
          </div>
        {% endif %}
      </div>
    </section>
  {% endif %}

  {% if node.field_related_how_tos.target_id %}
    <section class="hl__staggered-type-list">
      <div class="hl__staggered-type-list__list-wrapper">
        <div class="hl__staggered-type-list__list">
          {{ content.field_related_how_tos }}
        </div>
      </div>
    </section>
  {% endif %}
</article>

The more you try things, the more you are going to learn. You cannot do any PHP in Twig templates, which is why that has to be deferred to preprocess functions in the theme file, custom field formatters etc that tell Drupal what to do with the data you are about to output.

edit: the {% if node.field_name.value %} lines are simply checking in the node object that the field has an actual value before we output markup and render the field for it. node and content are two separate things.

  • This is a very thoughtful, helpful, and clear reply. I am going to pick through it shortly and really appreciate your time, @kevin. Thank you! – user1149499 Jan 10 at 17:39

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.