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.

Render a collection, handling both global and local components

On the frontend, a collection element's getComponent() already returns the global component when the element points at one, so one loop serves both. Guard for blank, and pass only new variable names down.

Context

Context. An author can drop a local component into a collection or place a global component (a footer call to action, a shared banner). In the frontend, the element's getComponent() returns whichever it is, already resolved to the global component's active version when it is global, so a template needs no branch. What it needs is a blank guard, and to pass down only variables the page does not already have.

Steps

  1. Fetch the elements once.
  2. For each, take getComponent() and skip it if blank (a deleted global component leaves a blank behind).
  3. Render with getHtml(), passing the position and anything else the block needs under names of your own.
  4. If you must know which kind it is, isGlobal() and isLocal() exist on the component; use them for a CSS hook, never to change what renders.

Template code

Template code
{$elements = $page->getAreaCollectionElements('main')}
{foreach $elements as $element}
  {$block = $element->getComponent()}
  {if $block->isBlank()}{continue}{/if}
  <div class="block{if $block->isGlobal()} block--global{/if}">
    {$block->getHtml(['blockIndex' => $element@iteration, 'loadPriority' => ($element@iteration <= 2) ? 'eager' : 'lazy'])}
  </div>
{/foreach}
{% set elements = page.getAreaCollectionElements('main') %}
{% for element in elements %}
  {% set block = element.getComponent() %}
  {% if not block.isBlank() %}
  <div class="block{% if block.isGlobal() %} block--global{% endif %}">
    {{ block.getHtml({'blockIndex': loop.index, 'loadPriority': loop.index <= 2 ? 'eager' : 'lazy'}) }}
  </div>
  {% endif %}
{% endfor %}

Why this and not that

Not a global-or-local branch that calls different methods: the resolution is done for you on the frontend, and a branch is one more thing to keep in step. Not getAreaHtml('main') when the blocks need context: it renders them all, but you cannot pass anything down. Not the name index for the position when the page already has one: a passed variable never overrides an existing one.

Go deeper

Was this page helpful?

Your answer goes to the docs team.