Custom fields type: Subfields
From Joomla! Documentation
Introduction
Custom fields in Joomla! is a technology to extend various item types (content articles, contact items, etc.) with custom-made fields, e.g. extending a content article with a text field named fact_checked_by. For a basic introduction into this topic see J3.x:Adding custom fields.
This wiki page is an introduction into a special type for custom fields called subfields. The aim of the subfields custom field type is to provide the user the possibility to create a repeatable custom field for an item with multiple related fields, so e.g. adding a custom field named ingredients with the sub fields description and amount to a content article.
A short note on terminology: We use the term "sub fields" to describe two different things: First, subfields is the type of the custom field that is being added to an item, so the type of the "parent field" - e.g. like other custom fields can be of type text or integer. Second, we call the configured "child fields" of that parent field "sub fields", just because that is comfortable. An attentive reader will note the difference, but the context should always be clear what is meant. If that is not the case, we use other terms.
The subfields field
Provides a possibility to add several (repeatable) sub fields to an item. The sub fields are each rendered by themselves and the result will by default be shown as a comma-separated list (this can be changed, see further down).
Options
- render_values (mandatory) boolean, default true.
Whether the value of the sub fields should get rendered. Normally you want this to be true, unless you are using a layout override to change the overall rendering of the custom field, in which case you can disable this and slightly increase the performance when evaluating the field. - repeat (mandatory) boolean, default true.
Whether the sub fields should be repeatable in the backend.
Changing the rendering with a layout override
By default, the value of all sub fields will be rendered and the result will be shown as a comma-separated list in the frontend. This default behavior is implemented in the file plugins/fields/subfields/tmpl/subfields.php, please take a look at it to get a first impression on how to change the rendering in general.
The first thing to do to change the rendering is to create a layout override for that template, e.g. by creating a new file templates/$YOUR_TEMPLATE/html/plg_fields_subfields/subfields.php, see Layout Overrides in Joomla for further info.
The next thing to do is to get an idea about the structure of the $field object that is being passed to the template. That object has 2 important properties:
- $field->name is a string containing the name of the custom field you set.
- $field->value is an array of rows containing the rendered name + value pair for each sub field, for each occurrence (if repeatable is enabled). If you want to create a layout override, you normally won't touch this property, as it is not very flexible.
- $field->subfield_rows is an array of objects, whereby each object represents one row of the sub fields. Every object / row has one property for each sub field (named by the sub fields' name), which again is an object with properties value and rawvalue, containing respectively the rendered and the unrendered value of that sub field for the given row.
You can use the name property to make distinctions in your template dependent of which field is being rendered.
Especially the subfield_rows property might sound a bit complicated in the first place, but when you create your layout override and play around with it, var_dump() different states etc. you should get a good feeling about how it behaves.
Example 1
Suppose we have created a custom field named ingredients for an article that contains the sub fields description and image of type text and media respectively. We now want to display those in a nice way when we are asked to render them. We could e.g. do this in the following way, note the different use of rawvalue and value here, which we use to get access to the rendered value of the media field (which is, normally, an <img> HTML tag):
<?php if ($field->name == 'ingredients'): ?>
<ul>
<?php foreach ($field->subfield_rows as $row): ?>
<li>
Description: <?php echo htmlentities($row->description->rawvalue); ?><br />
Image: <?php echo $row->image->value; ?>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
Example 2
The subfield_rows object can get a little complicated. The following code will render all sub fields in a comma-separated list, just like the original template does, but it uses the sub fields' rawvalue instead of the rendered value. This example shows how the subfield_rows object can be used in a more advanced way.
<?php
echo '<ul>';
foreach ($field->subfield_rows as $subfield_objects)
{
echo '<li>';
$buffer = array();
foreach (array_keys(get_object_vars($subfield_objects)) as $subfield_name)
{
$buffer[] = (
$subfield_name . ': '
. $subfield_objects->{$subfield_name}->rawvalue
);
}
echo implode(', ', $buffer);
echo '</li>';
}
echo '</ul>';