Nesting Components

Nest Bookshop components and create structured data within your components

The Bookshop blueprint of your component config can help configure some advanced Structure use-cases on CloudCannon.

Nesting components#

Your blueprint can reference other components and Structures, which will embed their structured data within. For example, this saves you from having to re-define the required inputs if your hero component contains an editable button component — using component nesting your blueprint might look like:

hero.bookshop.yml
copied
blueprint:
  hero_text: Hello World
  button: bookshop:button 

This is a string, and could also be written button: "bookshop:button".

In this example, the button key will become an Object Structure containing the values specified in your button component blueprint. If you desired an array of buttons, you could use the following:

hero.bookshop.yml
copied
blueprint:
  hero_text: Hello World
  buttons: 
    - bookshop:button

Or more concisely, buttons: [bookshop:button]

In general, any bookshop:<component_name> string will be replaced with the structure of that component, and will allow editors to add and remove that component.

Nesting a set of components#

If you're creating a layout component, you likely want to support a set of components. For this, you can reference the keys we defined in spec.structures:

section.bookshop.yml
copied
blueprint:
  section_label: My Section
  header: bookshop:structure:content_blocks 
  inner_components: [bookshop:structure:content_blocks] 

The header key will become a single component that can be selected from the set of components tagged as content_blocks

The inner_components key will become an array that can contain any components tagged as content_blocks

Nesting Example#

To give a concrete example, let's say we have an example hero component:

hero.bookshop.yml
copied
spec:
  structures: [content_blocks]

blueprint:
  hero_text: Hello World
  cta_button: bookshop:button
  column_components: [bookshop:structure:content_blocks]

Then our matching component template file might look like:

hero.eleventy.liquid
copied
<div class="hero">
  <h1>{{ hero_text }}</h1>
  {% if cta_button %} 
    {% bookshop "button" bind: cta_button %}
  {% endif %}
  {% for component in column_components %}
    {% bookshop "{{ component._bookshop_name }}" bind: component %}
  {% endfor %}
</div>

Object Structures in CloudCannon may be empty, as the component can be removed and replaced, so your template should check for the existence of this component.

Initializing Nested Components#

By default, nested components using the bookshop:* shorthand will be initialized empty. For example, the blueprint:

hero.bookshop.yml
copied
blueprint:
  hero_text: Hello World
  button: bookshop:button

Will be initialized in CloudCannon as:

page.md
copied
  - _bookshop_name: hero 
    hero_text: Hello World
    button:

Where the button input will provide an editor with the option to add a button component. To instead have the button component exist on creation, you can use the syntax bookshop:button!:

hero.bookshop.yml
copied
blueprint:
  hero_text: Hello World
  button: bookshop:button!

The same setting can be applied to a structure shorthand by specifying the component that should be initialized. Taking the following example:

section.bookshop.yml
copied
blueprint:
  section_label: Hello World
  column_components:
    - bookshop:structure:content_blocks!(hero)
    - bookshop:structure:content_blocks!(button)

This will be initialized in CloudCannon as:

page.md
copied
  - _bookshop_name: section 
    section_label: Hello World
    column_components:
      - _bookshop_name: hero
        # ... hero fields
      - _bookshop_name: button
        # ... button fields

Where column_components can be then further added to/removed from by an editor, using components from the tagged structure.

Open in a new tab