Creating Custom Component Fields Types
Hyvä Commerce is an 'Early Access' product currently under development.
Early Access means that not all features of Hyvä Commerce are fully completed or released, and many areas are still under heavy development and may change. However, it means you can get your hands on everything currently available and being worked on, with a license. Find out more on our Early Access page.
This is an advanced topic and should only be attempted by experienced developers. Be prepared to debug cases specific to your custom field type implementation.
Hyvä CMS allow you to define custom input fields for your components. These field types control how data is collected in the editor interface to be used in the frontend. This guide will walk you through creating custom field within your project, enabling you to build more sophisticated and tailored content components.
1. Configure the Field Type
First, we need to register our custom field type in the DI configuration and specify its template file that will be used in the editor interface.
<type name="Hyva\CmsLiveviewEditor\Model\CustomField">
<arguments>
<argument name="customTypes" xsi:type="array">
<item name="foobar" xsi:type="string">YourVendor_YourModule::field-types/foobar.phtml</item>
</argument>
</arguments>
</type>
2. Implement in Component Configuration
Next, we'll add our new custom field type to a component's configuration in components.json
, defining where it should be used within the component.
"your_component": {
"label": "Your Component",
"content": {
"foobar_field": {
"type": "custom_type",
"custom_type": "foobar",
"label": "Foo Bar Field",
"attributes": {
"pattern": ".*(foo|bar|Foo|Bar).*"
}
}
}
}
3. Create the Field Template
Create a new template file in your module's view directory.
<?php
declare(strict_types=1);
use Magento\Backend\Block\Template;
use Magento\Framework\Escaper;
use Hyva\CmsLiveviewEditor\Magewire\LiveviewComposer;
use Hyva\Theme\Model\ViewModelRegistry;
use Hyva\CmsLiveviewEditor\ViewModel\Adminhtml\FieldTypes;
/** @var Template $block */
/** @var Escaper $escaper */
/** @var LiveviewComposer $magewire */
/** @var ViewModelRegistry $viewModels */
/** @var FieldTypes $fieldTypes */
$fieldTypes = $viewModels->require(FieldTypes::class);
$uid = (string) $block->getData('uid');
$fieldName = (string) $block->getData('name');
$fieldValue = (string) $block->getData('value');
$attributes = (array) $block->getData('attributes') ?? [];
$filteredAttributes = $fieldTypes->getDefinedFieldAttributes($attributes);
$hasError = isset($magewire->errors[$uid][$fieldName]);
$errorMessage = $hasError ? $magewire->errors[$uid][$fieldName] : '';
?>
<div class="field-container" id="field-container-<?= $escaper->escapeHtmlAttr("{$uid}_{$fieldName}") ?>" <?= $hasError ? 'data-error' : '' ?>>
<input type="text"
name="<?= $escaper->escapeHtmlAttr("{$uid}_{$fieldName}") ?>"
value="<?= $escaper->escapeHtmlAttr($fieldValue) ?>"
@keydown.debounce.500="
updateField(
'<?= $escaper->escapeHtmlAttr($uid) ?>',
'<?= $escaper->escapeHtmlAttr($fieldName) ?>',
$event.target.value
)
"
class="field w-full form-input <?= $hasError ? 'error field-error ' : '' ?> <?= $escaper->escapeHtmlAttr($attributes['class'] ?? '') ?>"
<?php foreach ($filteredAttributes as $attr => $value): ?>
<?= $escaper->escapeHtmlAttr($attr) ?>="<?= $escaper->escapeHtmlAttr($value) ?>"
<?php endforeach; ?>>
<ul id="validation-messages-<?= $escaper->escapeHtmlAttr("{$uid}_{$fieldName}") ?>" class="validation-messages list-none">
<?php if ($hasError): ?>
<li class="error-message text-red-600 text-sm mt-1">
<?= $escaper->escapeHtml($errorMessage) ?>
</li>
<?php endif; ?>
</ul>
</div>
Important Markup Requirements
When creating custom field templates, the following markup requirements must be followed to ensure proper functionality:
Field Container
Include to following as your root element.
<div class="field-container" id="field-container-<?= $escaper->escapeHtmlAttr("{$uid}_{$fieldName}") ?>" <?= $hasError ? 'data-error' : '' ?>>
This ID format is required for validation to work correctly.
The data-error
attribute set by the magewire component variable $hasError
is required for validation highlighting to work.
Input Name
Add name="<?= $escaper->escapeHtmlAttr("{$uid}_{$fieldName}") ?>"
to your input field.
Required for frontend validation to work and for the the editor to focus on your field when users select its value in the editor preview.
Validation Messages Container
Include id="validation-messages-<?= $escaper->escapeHtmlAttr("{$uid}_{$fieldName}") ?>"
on a container for validation messages.
Required for validation messages to appear.
You can optionally specify a different container using data-validation-messages-selector
on the field container.
Field Value Updates
Two methods are available for updating field values:
updateField
: Bypasses Magewire to update preview directly via AJAX, reading from local state until saved. Ideal for debounced inputs.updateWireField
: Updates both preview and server state through Magewire immediately.
If adding your own Alpine components, you cannot set values through these methods within your component. Keep input fields outside your Alpine component and update them with vanilla JavaScript.
Input Attributes
The $inputAttributes
handling in the example above provides validation capabilities based on attributes passed in the component declaration. Hyvä CMS' built-in validation will validate the field against these HTML5 validation attributes. See Field Attributes and Validation for more information.
4. Dynamically Set the Field Value
Once you've created your custom field template, you have complete control over how the field value is set. You can:
- Use Magento's standard data providers (ViewModels, Blocks, Controllers)
- Fetch data via REST or GraphQL APIs
- Connect to external systems
- Implement custom business logic
Updating the Field Value
The field value is set through either the updateField
or updateWireField
method. If you are adding your own Alpine components, you cannot set the value through these method within your component. The input field should be kept outside of your Alpine component, your component can then update it with vanilla JavaScript.
Tip
For inspiration look at the field handlers in the Hyva_CmsLiveviewEditor::page/js/
adminhtml directory.