Theming Field Collections in Drupal 7

Field collections is a great module that extends your Drupal site capabilities by allowing you to have “groups” of fields. This becomes extremely useful when you need multiple groupings of fields.

If you’re a Drupal developer, you know how valuable this can be. If you’ve used Field Collections in the past, you know how frustrating it is to theme them! What follows is my best explanation of how they work—and sometimes don’t work—and hope to make sense of the awfulness that is templating field collections in Drupal.

Lets say you want an FAQs section on your content type. To accomplish this, you may set a field on your content type called “FAQs” of the type “field collection” (field collections must be created this way and seems a bit unintuitive).

drupal-01

Make sure that under “Number of Values” you select “unlimited”.

drupal-03

 

Once this is created, you can go to Structure -> Field Collections, and add fields to your newly created field collection like you would to a content type. Now create a text field called “Question” and a longtext field called “Answer”.

drupal-02

Once this is done, you have your new Field Collection Entity set up. A Field Collection is just a Drupal Entity. If you’re not familiar with Entities, you should read An Introduction to Entities, however that is not required reading for this blog post.

Now when you go to your content-type, you can see your field groupings and the “add another” beneath the groupings. Add a few items.

drupal-04

Once this is completed, click “save” and view your output:

When you look in the source code, you will no doubt see the divitis that always comes with Drupal.

drupal-06

Now comes the theming of the field collection. To understand this a bit more, remember there are three layers:

  • Your Entire Field Collection
    • Your First “Group” of fields
      • Field One
      • Field Two
    • Your Second “Group” of fields
      • Field One
      • Field Two

This translates to this in our content-type (color-coded for future clarity):

  • FAQs
    • “Grouping One”
      • Question 1
      • Answer 1
    • “Grouping Two”
      • Question 2
      • Answer 2

First, we are going to theme our top-level FAQs. To do this, we must know that:

  1. Field collections are fields of the content-type, and all sub-levels are a part of the field collection entity.
  2. Custom fields are always prefixed field_ and ours is “field_faqs” not “faqs”.
  3. When naming templates, replace underscores with hyphens, and when separating items, such as fields from content types, you use two consecutive hyphens.

The format for the top-most layer is:

field--[field_name].tpl.php

Since this top layer is a field and our field name is field_faqs, our final filename is:

field--field-faqs.tpl.php

In this file I have some basic code that, for the purposes of this demo, have in-line styling to show differentiation. There should be one cyan-colored box with a red border around all the fields.

<div id="faqs" style="background: cyan; border: 1px solid red;">
	<?php if (count($items) > 0) { ?>
		<h3>Frequently Asked Questions</h3>
	<?php } ?>
	<?php foreach ($items as $delta => $item): ?>
		<?php print render($item); ?>
	<?php endforeach; ?>
</div>

Click Save and flush cache (as theme registry has to be rebuilt). Here is the result:

drupal-07

Obviously something’s wrong… That’s because Field Collections has a known bug in that the template cascades down to all the items and fields in the field collection. This is a problem that, for now, can be solved by creating templates for each group and each field. So lets move on to the Group!

While the entire field collection is considered a field of the content type, the grouping of individual instances of this field (i.e. each collection), henceforth known as “item”, is a part of the field collection entity. The format of the individual item is:

field-collection-item--[field_name].tpl.php

So our grouping is named:

field-collection-item--field-faqs.tpl.php

In my file, here is the code I have:

<div class="item" style="background: orange; border: 1px solid green; padding: 5px">
    <?php
      print render($content);
    ?>
</div>

Save this and clear cache, and here’s what you’ll a green bar and orange padding around each item.

drupal-08

Finally, lets field the question and answer fields. This is in the format:

field--[field_name]--[field collection name].tpl.php

Our Question field would be:

field--field-question--field-faqs.tpl.php

I’ve added this code with red background:

<div class="faqs-question" style="background: red; color: white;">
<?php foreach ($items as $delta => $item): ?>
	<p><?php print render($item); ?></p>
<?php endforeach; ?>
</div>

The Answer field is:

field--field-answer--field-faqs.tpl.php

I’ve added this code with blue background:

<div class="faqs-answer" style="background: blue; color: white">
<?php foreach ($items as $delta => $item): ?>
	<?php print render($item); ?>
<?php endforeach; ?>
</div>

Save, clear cache, and see the results:

drupal-09

You can also see that our HTML is much simpler:

drupal-10

It’s not pretty, but you just themed field collections. Hopefully you came out understanding that:

  1. Field collections have three layers to them that must be themed uniquely
  2. Field collection templates cascade down
  3. Among the three unique layers, there is a very specific naming convention to the files within

Of course there’s more details that aren’t all covered here, like why field templates have an $item variable and the item template ironically doesn’t, but uses the $content variable. You can also refer to the documentation for fielding fields and field collections to find access to other variables.

Leave a Reply

Your email address will not be published. Required fields are marked *