Custom Components
To define a custom component, you need to create a component template file in the /components
directory and declare it in the template.config.js
file.
Component structure
A component consists of three parts - html template, styles and scripts. Those are all defined in the same template file.
Let's say you want to have a single reusable image, then you can create a my-image.html file in the components directory with the following content:
<!-- /components/my-image.html -->
<template>
<img src="https://placekitten.com/300/200" class="my-image">
</template>
<style>
.my-image {
border: 1px solid red;
&:hover {
border-color: blue;
}
}
</style>
<script>
const images = [].slice.call(document.querySelectorAll('.my-image'));
images.forEach((img, idx) => {
img.addEventListener('click', () => { console.log(idx); });
});
</script>
If you don't need any custom scripts or styles for you component, you can just put the image markup into the component file:
<!-- /components/my-image.html -->
<img src="https://placekitten.com/300/200" class="my-image">
Then you'd just need to add a components
configuration array to the template.config.js file:
// template.config.js
module.exports = {
name: 'My first template',
components: [
{ name: 'my_image', src: 'my-image.html' }
]
}
The component can then be rendered inside of any other template using the component macro:
{{@component(my_image)}}
Static components
Static components are reusable parts of code which can be used in your template parts, and/or inserted into a page/post.
Dynamic components
Dynamic components have to be instantiated before they can be added into a post/page. Let's say we want to create image gallery that can be reused across different posts.
First we'll create a gallery.html file in the /components directory with the following content:
<!-- /components/gallery.html -->
<div class="gallery">
<h3 class="gallery__title">{{title}}</h3>
<!-- iterate over the images list and render an image macro -->
<ul class="gallery__images">
{{#images}}
<li class="gallery__image">
{{@image(value, maxWidth=150)}}
</li>
{{/images}}
</ul>
</div>
To make the component instantiable, it needs to be connected in the template.config.js file, and the props the component will receive have to be defined:
// template.config.js
module.exports = {
name: 'My first template',
components: [
{
name: 'gallery',
src: 'gallery.html',
viewName: 'Gallery',
editorComponent: true,
props: [
{ name: 'title', viewName: 'Title', type: 'text' },
{ name: 'images', viewName: 'Images', type: 'list', itemType: 'image' }
]
}
]
};
Component declaration
A single component can be configured using the following settings:
name (required) - the name of the component, used for rendering or cross-referencing
viewName - the view name of the component, will be displayed in the Phaistos editor
src (required) - the name of the html file in the components directory
editorComponent - whether this component can be inserted in the content editor (
false
by default)props - an array of props the instantiated component will receive
Prop types
Any dynamic component can receive the following props:
text - short text
long_text - long text
image - an image
number - a number, by adding a min and/or max property you can also set the lower/upper limit
wysiwyg - rich text content
boolean - true/false value
select - a single value from a list of options, requires an options setting (array) with the following properties:
viewName - the view name of the option
value - the value of the option
list - an array of values, requires an itemType setting which can either be a primitive prop type (e.g. text) or another component (component item types require the componentType setting which expects the component name)
post - a post or page, see Template Parts documentation page