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
Patterns, live preview and upkeepPage 41 of 45Updated
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
Tool
What it does
Where it is set
Default content
Stands 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 placeholder
getAreaImageOrPlaceholder(name, width, height) returns a placeholder in place of an empty image area.
The setting Files.images.usePlaceholder
The empty test
The 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:
Getter
Returns when empty
Smarty test
Twig test
getAreaImage(), a component area, raw content
A blank object, never null
!$x->isBlank() (or isEmpty())
is not empty
getAreaCollectionElements()
An empty collection, never null
count($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().
{% 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.
{% 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.