# Adding custom elements

hostware offers a big CMS (Content management system) so hosting providers can easily manage their website along their core business.

The default hostware storefront, which is built with bootstrap 5, offers a large amount of Elements, which can be used to create stunning pages. However, modules and themes may want to create custom elements to enhance the amount of variation.

A cms element required four parts:

1. The element class (PHP)
2. The element, which is rendered in the storefront (twig)
3. The element preview, which is rendered in the administration (blade)
4. The element config, which is rendered in the administration (blade)

{% hint style="info" %}
The visual representation of cms elements in the administration does not need to be accurate, but should be identified to what is rendered in the storefront.
{% endhint %}

### Create the element class

The element class contains attributed like the label and technical name as well as the default config, which is loaded, when the element gets created by an administrator.

The class could look like this:

```php
<?php

namespace custom\themes\hw\hostx\Cms\Elements;

use App\Framework\Core\Cms\CmsElementInterface;

class HostX_FeatureBoxes implements CmsElementInterface {

    public function getName(): string {
        return "hostx_feature_boxes"; // <--- The technical name of the element, usually the class name in lower camel case
    }

    public function getLabel(): string {
        return "HostX Feature Boxen"; // <--- The label of the element, which gets displayed in the administration
    }

    public function getView(): string {
        return "theme.hostx::cms/elements/hostx_feature_boxes"; // <--- The path to the storefront view
    }

    public function getPreview(): string {
        return "theme.hostx::cms/elements/hostx_feature_boxes_preview"; // <--- The path to the administration view
    }

    public function getDefaultConfig(): array { 
        return [ // The default config
            "title" => "Our operating systems.",
            "subtitle" => "Your choice.",

            "item1_icon" => '<img class="lazy img-fluid" alt="businessman" src="/themes/hostx/img/icons/businessman.svg" style="">',
            "item1_title" => "Upgrade Management",
            "item1_text" => "It’s hard to believe anyone would want to harm your website, but they do. Thankfully!",

            "item2_icon" => '<img class="lazy img-fluid" alt="priority" src="/themes/hostx/img/icons/priority.svg" style="">',
            "item2_title" => "Priority Support",
            "item2_text" => "It’s hard to believe anyone would want to harm your website, but they do. Thankfully!",

            "item3_icon" => '<img class="lazy img-fluid" alt="mission" src="/themes/hostx/img/icons/mission.svg" style="">',
            "item3_title" => "Advanced Panel",
            "item3_text" => "Host unlimited domains, create unlimited email addresses, databases, FTP accounts, & more.",

            "item4_icon" => '<img class="lazy img-fluid" alt="hula hoop" src="/themes/hostx/img/icons/hula-hoop.svg" style="">',
            "item4_title" => "Flexible Management",
            "item4_text" => "Host unlimited domains, create unlimited email addresses, databases, FTP accounts, & more.",
        ];
    }

    public function provideData(array $config): array {
        // Can be used to load data, when the element gets loaded in the storefront
        return $config;
    }
}

```

### Load data on rendering

To load custom data when the element renders in the storefront, you can use the provideData() function in the element class. This function has the config array as parameter and needs to return that array. In the meantime, any items can be added or modified in the array.

An actual implementation could look like that:&#x20;

```php
public function provideData(array $config): array {
    $categoryIds = explode(",", $config['categoryIds']);

    // load category models from database
    $config['categories'] = Category::findMany($categoryIds); 

    return $config;
}
```

{% hint style="info" %}
The response of provideData() will be cached automatically
{% endhint %}

{% hint style="warning" %}
This doc page is incomplete.
{% endhint %}
