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.

Restrict which components an author may add to a collection

Supported layouts on the layout area decide what the add menu offers. Fill them in on every collection and component area; an empty list offers every component layout on the site, including the block itself.

Context

Context. Left alone, a collection area offers the author every component layout on the site, fifty on a mature one, including the very block the collection sits in, so a block can be placed inside itself. The supported layouts list on the layout area is the whole control: what is in it is offered, nothing else is. It is applied by the admin's editor, so a template still guards for an unexpected block rather than assuming the list was followed.

Steps

  1. Open the collection (or component) area on the layout and set its supported layouts to the handful of blocks that belong in that position.
  2. Do the same on every collection inside a component, which is where nesting gets out of hand.
  3. Check the list after retiring a layout: a list naming only hidden layouts, or layouts from another site, offers nothing at all.
  4. Keep the template loop tolerant of an unexpected block: supported layouts can change after content already exists, so older content can still hold one no longer on the list.

Code

Template code
{* the loop stays tolerant: an unexpected component still renders through its own template *}
{foreach $component->getAreaCollectionElements('columns') as $element}
  {$column = $element->getComponent()}
  {if $column->isBlank()}{continue}{/if}
  <div class="col">{$column->getHtml()}</div>
{/foreach}
{% for element in component.getAreaCollectionElements('columns') %}
  {% set column = element.getComponent() %}
  {% if not column.isBlank() %}<div class="col">{{ column.getHtml() }}</div>{% endif %}
{% endfor %}
JavaScript
// what the API accepts into a collection, whatever the supported layouts say:
{ "revision": { "areas": { "columns": [
  { "name": "Text column", "layout": "column-text", "areas": { "body": "<p>…</p>" } }
] } } }

Why this and not that

Not documentation for authors saying which blocks to use where: the picker enforces it and a note does not. Not hiding layouts to shrink the menu: hiding retires a layout everywhere; the supported list scopes it to a position. Tags and categories on components exist but only filter the global-components tab of the picker, so they are not a substitute.

Go deeper

Was this page helpful?

Your answer goes to the docs team.