Guide 04 · Developer docs

Input types, layouts, components and images

The platform's central abstraction, in one line: an input type defines what an editor can enter, a layout area binds one input type to a named slot, a layout groups areas and points at a template, a record or component holds the content for each area, and the template reads it back. Read this book straight after the template languages.

L1–L3
Unit 09 · Patterns, live preview and upkeep

Safe defaults, placeholders and the adaptive component

How an unfinished page can render something intentional: default content, the image placeholder, the empty test that fits each getter, and when a missing value should hide the whole block. Then the adaptive component, and why to use it sparingly.

Who this is for. Developers whose templates authors fill in gradually. After this page a half-finished page on your site degrades exactly the way you choose, every time.

Four tools, from the most structural

ToolWhat it doesWhere it is set
Default contentStands in for a value the author has not entered: the layout area's default content, or failing that its input type's.On the layout area or the input type, in the admin
The image placeholdergetAreaImageOrPlaceholder(name, width, height) returns a placeholder in place of an empty image area.The setting Files.images.usePlaceholder
The empty testThe template leaves out markup when a value is missing.In the template
hasAreaWithName()The template checks that the layout has the area at all.In the template

Default content

Default content is the cheapest: authors see it in the page, the template needs no branch, and it is changed in the admin rather than in a release. How to set it, and how it interacts with validation, is on Validation and default content. An area that still shows its default cannot be edited in place in live preview; see What stops an area being editable in place.

The image placeholder

Whether the placeholder is used is set by Files.images.usePlaceholder. Its default, loggedIn, shows it only to a signed-in user, and a signed-in site member counts as well as an admin. A signed-out visitor does not get the placeholder: it shows authors where an image is missing, without showing it to the public. Keep the empty test around images that a visitor may see empty. The accessor is described on From an image area to an image, the setting on Image settings.

The empty test depends on what the getter returns

There is no single empty test. Each getter returns a different kind of value when the area is empty, and the test has to fit it:

GetterReturns when emptySmarty testTwig test
getAreaImage(), a component area, raw contentA blank object, never null!$x->isBlank() (or isEmpty())is not empty
getAreaCollectionElements()An empty collection, never nullcount($x)is not empty
getAreaText()An empty string or null!empty($x)is not empty
getAreaValues()An empty array!empty($x)is not empty
getAreaRecord(), getAreaRecords()Null!empty($x)is not empty

Twig's is empty is safe on blank objects because the platform replaces Twig's own test with one that knows them. Smarty has no such replacement. The full table, getter by getter, is on Testing whether an area is empty.

empty() on an object is always false

In Smarty, {if !empty($component->getAreaImage('icon'))} is true whether or not the author chose an icon. getAreaImage() returns a blank image object, never null, and PHP's empty() is false for every object. The page then prints an empty image. Test images, components and raw content with isBlank().

Template code
{$img = $component->getAreaImage('hero')}
{if !$img->isBlank()}{$img->getHtml()}{/if}
{$related = $component->getAreaRecords('related')}
{if !empty($related)}
  <ul>{foreach $related as $r}<li>{$r->getName()|escape}</li>{/foreach}</ul>
{/if}
{% set img = component.getAreaImage('hero') %}
{% if img is not empty %}{{ img.getHtml() }}{% endif %}
{% set related = component.getAreaRecords('related') %}
{% if related is not empty %}
  <ul>{% for r in related %}<li>{{ r.getName()|e }}</li>{% endfor %}</ul>
{% endif %}

When the layout does not have the area

A template that more than one layout uses may read an area that only some of those layouts have. In Smarty, the shorthand for an area the layout does not have raises Property eyebrow does not exist; Twig prints nothing. Test with hasAreaWithName() before reading such an area.

Template code
{if $component->hasAreaWithName('eyebrow') && !empty($component->getAreaText('eyebrow'))}
  <p class="eyebrow">{$component->eyebrow}</p>
{/if}
{% if component.hasAreaWithName('eyebrow') and component.getAreaText('eyebrow') is not empty %}
  <p class="eyebrow">{{ component.eyebrow }}</p>
{% endif %}

When a missing value should hide the whole block

The empty test answers whether a value is there. Whether the block survives without it is a design decision, made once per component and written in its template header:

  • Hide the block when the missing value is what the block is for: a quote component with no quote, a call to action with no link. Render nothing rather than an empty frame.
  • Render the block without the piece when the value supports the rest: an icon, an eyebrow, a secondary link.
  • Use default content when the block must always say something, such as the standard wording of a sign-up panel.
  • Do not write fallback copy into the template. It reaches the public, and authors cannot change it. Default content on the layout area is visible to authors and edited in the admin.

The adaptive component

A layout area's input type, and so its category, is fixed on the layout. An adaptive component is one template serving several layouts whose area of the same name has a different type: a media area that is an image on one layout, a text area on another and a record picker on a third. The template asks for the category, {$kind = $component->getAreaCategory('media')}, and calls the getter that fits it, one branch per category. The framework builds its own rendering of non-text content the same way. The full example, in both engines, is on Area introspection, raw content and attributes.

Use it sparingly

Each branch is a separate path to build, style and test, and an author cannot tell from the form which variant a layout gives. It is rare on production sites. Prefer separate component layouts with their own templates, and reach for an adaptive component only when the variants share almost all their markup and differ in one slot.

Go deeper

Was this page helpful?

Your answer goes to the docs team.