Components

Components help you organize blocks of markup that you use often by extracting them to a file, so you can reuse them in multiple templates.

Usage

To create a Component, simply create an HTML file with a <content> tag:

src/components/example.html
<content></content>

The <content> tag will be replaced with the content passed to the Component.

You may use the <component> tag to insert a Component in a Template:

src/templates/example.html
<component src="src/components/example.html">
  This text will replace the `<content>` tag in the Component.
</component>

Configuration

You may define where you keep your Components and what markup they use.

Attribute

Use a custom attribute name:

config.js
module.exports = {
  build: {
    components: {
      attribute: 'href',
    }
  }
}

You can now use it like this:

src/templates/example.html
<component href="src/components/example.html">
  Content to pass inside component...
</component>

Tag

Use a custom tag name:

config.js
module.exports = {
  build: {
    components: {
      tag: 'module',
    }
  }
}

You can now use it like this:

src/templates/example.html
<module src="src/components/example.html">
  Content to pass inside component...
</module>

Root

By default, when using a Component you have to reference its path relative to your project root (like we did above).

However, you may customize this path:

config.js
module.exports = {
  build: {
    components: {
      root: 'src/components',
    }
  }
}

Now you can reference them relative to that root path, and write less code:

src/templates/example.html
<component src="example.html">
  Content to pass inside component...
</component>

Example

Let's create a VML background image Component to which we pass data about the image and the HTML to be overlayed on top of it.

We might imagine something like this:

src/components/v-fill.html
<!--[if mso]>
<v:rect stroke="false" style="width: {{ width }}" xmlns:v="urn:schemas-microsoft-com:vml">
<v:fill type="frame" src="{{{ image }}}" />
<v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text: true"><div><![endif]-->
<content></content>
<!--[if mso]></div></v:textbox></v:rect><![endif]-->

The content of the component or, in our case, the HTML to be placed over the image, will be output in place of the <content> tag.

The variables that we are referencing in there are currently undefined, so let's create them in Front Matter and pass them to the component:

src/templates/example.html
---
image:
  url: 'https://example.com/image.jpg'
  width: '600px'
---

<extends src="src/layouts/main.html">
  <block name="template">
    <component
      src="src/components/v-fill.html"
      image="{{ image.url }}"
      width="{{ image.width }}"
    >
      <div>
        Overlayed HTML!
      </div>
    </component>
  </block>
</extends>

Result:

build_production/example.html
<!--[if mso]>
<v:rect stroke="false" style="width: 600px" xmlns:v="urn:schemas-microsoft-com:vml">
<v:fill type="frame" src="https://example.com/image.jpg" />
<v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text: true"><div><![endif]-->
<div>
  Overlayed HTML!
</div>
<!--[if mso]></div></v:textbox></v:rect><![endif]-->

Variables

When creating a Component, you have access to global variables:

src/components/example.html
<div>
  Building for: {{ page.env }}
</div>

You can also manually provide data to the Component through attributes:

src/templates/example.html
<component
  src="src/components/example.html"
  env="{{ page.env }}"
  role="user"
>
  Building for: {{ env }}
  Role is: {{ role }}
</component>

Undefined variables

Sometimes you may need to use a Component without passing it the variables it uses. However, if you try to use an undefined variable in a Component, the build will fail.

For example, if you have this Component:

src/components/example.html
<div>
  Category: {{ category }}
</div>

... and try to use it like this:

src/templates/example.html
<component
  src="src/components/example.html"
></component>

... the build will fail.

To work around it, you can do a type check when using the variable:

src/components/example.html
<div>
  Category: {{ typeof category !== 'undefined' ? category : 'Uncategorized' }}
</div>

If you're using an <if> tag, you may check the type like this:

src/components/example.html
<if condition="typeof category !== 'undefined'">
  <div>
    Category: {{ category }}
  </div>
</if>

Ignoring expressions

Ignoring expressions inside a Component works as you'd expect:

src/components/example.html
Hello @{{ name | fallback: 'friend' }}!

<content></content>

Of course, you can ignore expressions when passing data or content to the Component:

src/templates/example.html
<component
  src="src/components/example.html"
  role="@{{ user.role }}"
>
  Hello @{{ name | fallback: 'friend' }}!

  <raw>
    @{{ foo }}
  </raw>
</component>

Ignoring raw blocks

There's just one caveat: ignoring expressions inside <raw> blocks that you pass inside a component will only work like this:

src/templates/example.html
<component src="src/components/example.html">
  <raw>
    @{{ foo }}
  </raw>
</component>
Copyright © 2022 Maizzle SRL Brand policy
Edit this page on GitHub