Custom Elements

Create your own custom elements for the YOOtheme Pro page builder.

With a child theme you can add your own custom elements to the builder. Duplicate existing ones and change the markup and settings to your needs or create completely new elements that you can add to your projects.


Example Element

To get you started, we provide an example element that makes use of all the different field types and demonstrates the features described in the following chapter. Unzip the example files and place them in a builder directory of your child theme, for example yootheme_NAME/builder/example-element. Replace NAME with the name of our child theme.

Download Example Element


Adding Elements

Create a builder folder in your child theme. All subfolders within builder will be loaded as custom elements. Always make sure to give a unique element name that is not taken by the default builder elements. You can find the existing names in yootheme/vendor/yootheme/theme/builder – or you could just prefix your element with my- to be on the safe side, e.g. my-gallery.

For instance, let us go through the files of the example element that we provide to download. This example assumes you have placed the files inside your child theme.

yootheme_child/
    builder/
        example-element/
            example-element.json
            example-element-item.json
            template.php
            index.php
            icon.svg
            icon-small.svg
    ...

In template.php we will be rendering the markup of our element when it is displayed on the website. The template uses plain PHP for rendering and can access all element properties from the $element Collection object. Additionally, the template renderer provides a helper to automatically produce attributes for html tags, using $this->attrs().

<div <?= $this->attrs(['id' => $element['id'], 'class' => $element['class']]) ?> ?>

    <p><?= $element['field_text'] ?></p>

    ...

</div>

In example-element.json we define the element's name, icons and how the editing interface should look like inside the builder. The following example shows the object that defines the element type. It will be loaded in index.php, and the element will be added to the builder in the builder.init event. The example code explains the purpose of each property.

Note Make sure you adjust the path to your element's icon and iconSmall images. Otherwise, they will not be displayed in the overview of the element library.

// Define the element's name, icons and the available fields
{
    // Name of the element
    "name": "example_element",

    // Label in the interface
    "title": "Example Element",

    // Icon in `New element` dialog
    "icon": "${THEME}_child/builder/example-element/icon.svg",

    // Icon in builder overview
    "iconSmall": "${THEME}_child/builder/example-element/icon-small.svg",

    // Show in `New element` dialog
    "element": true,

    // Set default values for fields
    "default": {
        // <field_name>: <default_value>
        "field_text": "John Doe"
    },

    // Define the available fields for the element
    "fields": {
        // <field_name>: <field_definition>
        "field_text": {
            "type": "text",
            "label": "Field text",
            "description": "A short description that will be displayed below the field."
        },
        "style": {
            "type": "select",
            "label": "Style",
            "description": "Select one of the boxed card styles or a blank module.",
            "default": "",
            "options": {
                "Blank": "",
                "Card Default": "card-default",
                ...
            }
        }
    },

    // You can define different tabs for the element and assign the previous defined fields to tabs.
    // This is optional. When not defined, all fields will be displayed on one page.
    "fieldset": {
        "default": {
            "type": "tabs",
            "fields": [
                {
                    "title": "Content",
                    "fields": ["field_text"]
                },
                {
                    "title": "Settings",
                    "fields": ["style"]
                }
            ]
        }
    }
}

In the index.php file we define the internal name of our element and add the element in the builder.init event. If you rename your element from example_element to something else, make sure to also rename all references to files and internal identifiers in this file.

<?php

return [

    // Module name
    'name' => 'yootheme/builder-example-element',

    // How this element is referenced inside the builder
    'builder' => 'example_element',

    // Render this element on the website
    'render' => function ($element) {
        return $this->view->render("{$this->path}/template", ['element' => $element]);
    },

    'events' => [

        // Register the element in the builder
        'builder.init' => function ($elements, $builder) {
            $elements->set('example_element', json_decode(file_get_contents("{$this->path}/example-element.json"), true));
        }

    ],

    'config' => [

        'element' => true

    ]

];

You can now use the element inside the page builder. When you add a new element, it will appear at the end of all available element types. If it does not appear there, make sure you have enabled the child theme and check your browser developer console for error messages that could possibly result from the JavaScript code.

Example element in the element library


Fields

An element consists of a number of fields that are displayed in the page builder to enter content and change settings. These fields are then used to render the element inside YOOtheme Pro.

Each field has a type, by default it's type: text. The field will display an input field to enter text which can be rendered by the template. YOOtheme Pro provides a comprehensive collection of fields, e.g. for numbers and booleans as well as more complex ones, like an image, location or color picker.

You can define the fields inside the JSON object of example-element.json. Add field name and field definition to the fields object, then you can optionally define different tabs where the fields should be shown in the fieldset definitions. Here is an example with a text, select and checkbox field.

...
"fields": {

    // Text (default, if type is not set), defines an input field
    "field_one": {
        "label": "Text",
        "type": "text"
    },

    // Select, defines an select box
    "field_two": {
        "label": "Select",
        "description": "Explanation that appears below the field",
        "type": "select",
        "text": "Field Text",
        "options": {
            "Option 1": 0,
            "Option 2": 1,
            "Option 3": 2
        }
    },

    // Checkbox, defines a checkbox
    "field_three": {
        "label": "Checkbox",
        "description": "Explanation that appears below the field",
        "type": "checkbox",
        "text": "Field Text"
    }
},
// Optional define tabs and assign fields
"fieldset": {
    "default": {
        "type": "tabs",
        "fields": [
            {
                "title": "Content",
                "fields": ["field_one", "field_two", "field_three"]
            },
            {
                "title": "Settings",
                "fields": []
            }
        ]
    }
}
...

Settings of the the example element

When rendering the template, the value of the field is of the according type, or null if the user has not entered a value yet.

<?php
    echo gettype($element['field_one']);   // string
    echo gettype($element['field_two']);   // integer
    echo gettype($element['field_three']); // boolean
?>

Field Attributes

Every field is defined by its type and its attributes. The following attributes are available for all field types.

Attribute Description
label The field label is displayed as a headline in the element settings on the left.
description The field description is displayed as muted text below the field.
attrs This adds additional HTML attributes to the rendered field.

Here is an example of a text field.

{
    "label": "Text",
    "description": "Muted text that appears below the field",
    "type": "text",
    "attrs": {
        "placeholder": "Enter text..."
    }
}

Field Types

You can use a number of different fields to add content and settings to your element. Here is a list of all field types.

Name Type Description
Text text Define an input field. This is also the default if no field type is set.
Select select Define a select box – see example.
Number number Define a numerical input field.
Checkbox checkbox Define a checkbox – see example.
Radio radio Define a group of radio buttons – see example.
Range range Define an range slider with an addition input field – see example.
Textarea textarea Define a plain text area for multiple lines of text – see example.
Editor editor Define a visual and code editor (Depending on the Joomla settings) – see example.
Image image Define an image picker using the media library.
Video video Define a video picker using the media library.
Link link Define a link picker for Joomla system links and files in the media library.
Color color Define a color picker.
Font font Define a font picker.
Icon icon Define an icon picker for the UIkit icon library.
Location location Define an interactive map to pick a location.
Select-img select-img Define an image picker for a predefined set of images – see example.
Select-icon select-icon Define an icon picker for a predefined set of icons – see example.
Grid grid Arrange any field types in a grid next to each other – see example.

Select Example

Additional attributes are: default, options

{
    "label": "Select",
    "type": "select",
    "default": 0,
    "options": {
        "Option 1": 0,
        "Option 2": 1,
        "Option 3": 2
    }
}

Checkbox Example

Additional attributes are: text

{
    "label": "Checkbox",
    "type": "checkbox",
    "text": "The text behind the checkbox."
}

Radio Example

Additional attributes are: default, options, name

{
    "label": "Radio",
    "type": "radio",
    "name": "radio_group",
    "default": 0,
    "options": {
        "Option 1": 0,
        "Option 2": 1,
        "Option 3": 2
    }
}

Range Example

{
    "label": "Range",
    "type": "range",
    "attrs": {
        "min": 1,
        "max": 10,
        "step": 0.5
    }
}

Text area Example

{
    "label": "Textarea",
    "type": "textarea",
    "attrs": {
        "rows": 10,
        "placeholder": "Enter text..."
    }
}

Editor Example

Here is a list of additional attributes.

Attribute Description
editor Define which editor to load, i.e. code to disable the visual editor.
mode Explicitly define code language, e.g. css, js or text/html.

Note You often want to set a debounce attribute of around 500 milliseconds to prevent the live preview from updating while you are still typing in the editor.

Example for a visual and code editor.

{
    "label": "Editor",
    "type": "editor"
}

Example for a code editor only.

{
    "label": "Code editor",
    "type": "editor",
    "editor": "code",
    "mode": "css",
    "attrs": {
        "debounce": 500
    }
}

Select-img Example

Additional attributes are: title, default, options

{
    "label": "Select-img",
    "title": "Select an image",
    "type": "select-img",
    "default": "1-1",
    "options": {
        "1-1": {
            "label": "Whole",
            "src": "$ASSETS/images/whole.svg"
        },
        "1-2": {
            "label": "Halves",
            "src": "$ASSETS/images/halves.svg"
        },
        "1-3": {
            "label": "Thirds",
            "src": "$ASSETS/images/thirds.svg"
        }
    }
}

Select-icon Example

Additional attributes are: options

{
    "label": "Select-icon",
    "type": "select-icon",
    "options": {
        "": {
            "label": "Always",
            "icon": "phone",
        },
        "s": {
            "label": "Small (Phone Landscape)",
            "icon": "phone-landscape",
        },
        "m": {
            "label": "Medium (Tablet Landscape)",
            "icon": "tablet-landscape",
        },
        "l": {
            "label": "Large (Desktop)",
            "icon": "laptop",
        },
        "xl": {
            "label": "X-Large (Large Screens)",
            "icon": "desktop",
        }
    }
}

Grid Example

Additional attributes are: fields

{
    "type": "grid",
    "fields": {
        "field_grid_one": {
            "label": "Text 1",
            "width": "1-2"
        },
        "field_grid_two": {
            "label": "Text 2",
            "width": "1-2"
        }
    }
}

Content Items

It’s possible to define repeatable content items in your element, like the default Grid and Slideshow elements do.

An item is similar to a page builder element itself, which means that you have to register it with the page builder before you can use and display it.

Just like the element itself, a custom content item is defined via a JSON object. The following example is taken from the builder/example-element/example-element-item.json file that you’ll find in the example download:

// Define a content item used in your element
{
    "name": "example-element-item",

    "title": "Item",

    "width": 600,

    "fields": {
        // Text
        "content": {
            "label": "Content",
            "type": "text"
        },

        // Link (Using a predefined field)
        "link": "${LINK}",

        // Image (Using a predefined field)
        "image": "${IMAGE}",

        // Image
        "image2": {
            "label": "Image 2",
            "type": "image"
        }
    },

    "fieldset": {
        "default": {
            "fields": [
                "content",
                "link",
                "image",
                "image2"
            ]
        }
    }
}

To register this item we need to add it in index.php in the builder.init event where the element itself is already loaded.

'events' => [

    // Register the element in the builder
    'builder.init' => function ($elements, $builder) {
        $elements->set('example_element', json_decode(file_get_contents("{$this->path}/example-element.json"), true));

        // Additional register the custom element item
        $elements->set('example_element-item', json_decode(file_get_contents("{$this->path}/example-element-item.json"), true));
    }

],

This adds a field to your builder element that shows an interface to manage these custom content items. Additional attributes are: item and button.

// Content items
"field_content": {
    "label": "Content Items",
    "type": "content-items",
    "item": "example_element_item",
    "title": "content"
}

The YOOtheme Pro builder element will then show a list of content elements the user can order and remove:

Content items field

YOOtheme Pro