How-to library · Developer docs

How-to library

Task-shaped pages: a title that starts with a verb, the situation in a few lines, the steps, the working code in both engines, and why this way rather than another. Found from a search, done, and left.

Decide between a custom field and a layout area

Areas are for content an author composes on a record that has a layout; custom fields are for structured attributes on records that do not. Pages and posts take areas; people, menus, categories, tags and SEO settings take fields.

Context

Context. Both hold a typed value with the same input types. The difference is what they attach to. An area belongs to a layout and holds content an author composes for one record: a page's hero heading, a post's body. A custom field belongs to an entity type and holds an attribute every record of that type has, on types that have no layout: a person's job title, a menu element's icon, a category's landing image, an Open Graph type on SEO settings.

Steps

  1. Ask what the value attaches to. A page, post, FAQ question, custom entity record or component: a layout area. A person, user, author, address, category, tag, menu, menu element, form, product, product category or SEO settings: a custom field. Layouts and the three book levels take both.
  2. Ask whether an author composes it per record (area) or it is a property with the same meaning on every record (field).
  3. Define it where it belongs and read it with the matching getter.

Template code

Template code
{* an area on a page *}
<h1>{$page->heading}</h1>

{* custom fields on a menu element and a category *}
{$icon = $element->getCustomFieldText('icon')}
{if $icon}<span class="icon icon--{$icon|escape}"></span>{/if}
{$landing = $category->getCustomFieldImage('landingImage')}
{if $landing}{$landing->getResized(1200, 400, 'fit')->getHtml()}{/if}
<h1>{{ page.heading }}</h1>

{% set icon = element.getCustomFieldText('icon') %}
{% if icon %}<span class="icon icon--{{ icon|e }}"></span>{% endif %}
{% set landing = category.getCustomFieldImage('landingImage') %}
{% if landing %}{{ landing.getResized(1200, 400, 'fit').getHtml() }}{% endif %}

Why this and not that

Two borderline cases resolved: a menu element's mega-menu switch is a custom field (no layout, per element, read while looping); a "featured" flag on a page is a layout area on the page's layout, and finding featured pages is a tag, because a value inside a revision is not something a listing can filter on. Groups do not accept custom fields; put the attribute on the people or on a tag. A field made required later blocks the next save of every record missing it, so fill it first.

Go deeper

Was this page helpful?

Your answer goes to the docs team.