Widget PHP Implementation
Each widget is powered by a PHP class that implements Hyva\AdminDashboardApi\Api\V1\WidgetTypeInterface, or one of
the chart-type marker interfaces that extend it. The contract is shipped by the
Hyva_AdminDashboardApi module, and only that package needs to be required
by a module that exposes a widget. The dashboard runtime is not a build-time dependency.
Migrating from the legacy contract
Earlier versions of the dashboard used an inheritance-based contract in which widgets extended
Hyva\AdminDashboardFramework\Model\WidgetType\AbstractWidgetType. That contract continues to work, since the
dashboard runtime bridges both APIs through WidgetTypeDispatcher, but new widgets should use the
composition-based API described on this page. See the
1.3.0 upgrade notes for the mechanical migration
steps, or the legacy reference for the pre-2.0.0 method signatures.
Picking an Interface
A widget class implements either:
Hyva\AdminDashboardApi\Api\V1\WidgetTypeInterfacedirectly.- One of the chart-type marker interfaces in
Hyva\AdminDashboardApi\Api\V1\ChartType\, when the widget matches a built-in chart shape. Implementing one of these interfaces tells the framework to wire the matching defaults provider into theWidgetContextInterface, so the standard configurable and display properties for that chart type appear in the context object.
| Marker interface | Matching display_type |
Bundled defaults |
|---|---|---|
BarChartWidgetTypeInterface |
bar_chart |
Chart appearance options. |
LineChartWidgetTypeInterface |
line_chart |
Chart appearance options. |
PieChartWidgetTypeInterface |
pie_chart |
Chart appearance options. |
NumberWidgetTypeInterface |
number |
Number tile formatting. |
DateIntervalWidgetTypeInterface |
varies | default_interval display property and helpers. |
WidgetContextInterface
Every method on WidgetTypeInterface receives a Hyva\AdminDashboardApi\Api\V1\WidgetContextInterface $ctx object as
its first argument. The context is a read-only value object built by the framework's WidgetContextFactory from the
merged widget XML and, when applicable, the chart-type defaults provider. Wherever a legacy widget called
parent::method(), a new-contract widget calls $ctx->method() instead.
The WidgetContextInterface context exposes:
getId(): string, the widget's XMLidattribute.getTitle(): Phrase, the title taken from the merged widget XML.getAcl(): ?string, the ACL resource declared in the widget XML, if any.getTrailingAction(): array, the trailing-actionarray{title?, href?, target?}from the widget XML.getOption(string $key): mixed, a generic accessor for any merged-config option.toArray(): array, the full merged-config map, used by the framework'sGetHtmlcontroller as thetype_dataJS payload.isAllowed(?WidgetInstanceInterface $widgetInstance): bool, the default ACL plus ownership check.getDisplayProperties(): array, the chart-type default display properties.getConfigurableProperties(): array, the chart-type default configurable properties.
A Minimal Widget Example
Here's what a minimal widget type class looks like. This example bar-chart widget returns data to the frontend via
getDisplayData() and uses a fetchSeries() helper, but otherwise defers entirely to the widget context object:
use Hyva\AdminDashboardApi\Api\V1\ChartType\BarChartWidgetTypeInterface;
use Hyva\AdminDashboardApi\Api\V1\WidgetContextInterface;
use Hyva\AdminDashboardApi\Api\V1\WidgetInstanceInterface;
use Magento\Framework\Phrase;
class OrderVolume implements BarChartWidgetTypeInterface
{
public function __construct(private OrderRepositoryInterface $orderRepo) {}
public function getDisplayData(WidgetContextInterface $ctx, WidgetInstanceInterface $i): mixed
{
return [
'series' => [['name' => 'Orders', 'data' => $this->fetchSeries($i)]],
'xaxis' => ['categories' => ['Mon','Tue','Wed','Thu','Fri','Sat','Sun']],
];
}
public function getTitle(WidgetContextInterface $ctx, ?WidgetInstanceInterface $i): Phrase { return $ctx->getTitle(); }
public function getConfigurableProperties(WidgetContextInterface $ctx): array { return $ctx->getConfigurableProperties(); }
public function getDisplayProperties(WidgetContextInterface $ctx): array { return $ctx->getDisplayProperties(); }
public function getTrailingAction(WidgetContextInterface $ctx, ?WidgetInstanceInterface $i): array { return $ctx->getTrailingAction(); }
public function isAllowed(WidgetContextInterface $ctx, ?WidgetInstanceInterface $i): bool { return $ctx->isAllowed($i); }
public function beforeSave(WidgetContextInterface $ctx, WidgetInstanceInterface $i): WidgetInstanceInterface { return $i; }
public function afterSave(WidgetContextInterface $ctx, WidgetInstanceInterface $i): WidgetInstanceInterface { return $i; }
private function fetchSeries(WidgetInstanceInterface $i): array { /* ... */ }
}
Extending Defaults
To add a widget-specific property on top of the chart-type defaults, merge the existing array:
use Hyva\AdminDashboardApi\Api\V1\ChartType\DateIntervalWidgetTypeInterface;
use Hyva\AdminDashboardApi\Api\V1\Service\WidgetDateIntervalHelperInterface;
use Hyva\AdminDashboardApi\Api\V1\WidgetContextInterface;
use Hyva\AdminDashboardApi\Api\V1\WidgetInstanceInterface;
class DailyOrderVolume implements DateIntervalWidgetTypeInterface
{
public function __construct(private WidgetDateIntervalHelperInterface $intervalHelper) {}
public function getDisplayProperties(WidgetContextInterface $ctx): array
{
return array_merge($ctx->getDisplayProperties(), [
'highlight_today' => [
'label' => __('Highlight today'),
'input' => ['type' => 'toggle'],
],
]);
}
public function getConfigurableProperties(WidgetContextInterface $ctx): array
{
return array_merge($ctx->getConfigurableProperties(), [
'store_ids' => [
'label' => __('Store Views'),
'input' => ['type' => 'scope', 'attributes' => ['multiple' => true, 'required' => true]],
],
]);
}
public function getDisplayData(WidgetContextInterface $ctx, WidgetInstanceInterface $i): mixed
{
return [
'intervals' => $this->intervalHelper->getIntervalDataWithTimestamps(),
// ...
];
}
// The remaining methods delegate to $ctx exactly as in the previous example.
}
As a general rule: read everything from $ctx, and only array_merge(...) when you need to add your own properties.
Methods that don't add anything (getTitle, getTrailingAction, isAllowed, the save hooks) can just return the
context object's method calls.
Method Reference
Each method below uses the signature from Hyva\AdminDashboardApi\Api\V1\WidgetTypeInterface. All $ctx parameters are
an instance of WidgetContextInterface.
getDisplayData()
public function getDisplayData(WidgetContextInterface $ctx, WidgetInstanceInterface $widgetInstance): mixed
Produces the data the widget renders. The shape largely depends on the widget's display_type
or the expectations in whatever template consumes it.
$widgetInstance is a saved configuration for this type of widget. Configured values can be read via
$widgetInstance->getPropertyValue(...).
getTitle()
public function getTitle(WidgetContextInterface $ctx, ?WidgetInstanceInterface $widgetInstance): Phrase
Returns the title rendered at the top of the widget card. $widgetInstance is null when the widget has not yet been
created. Implementations that vary the title by configuration should fall back to $ctx->getTitle() in the null case.
getConfigurableProperties()
Returns the input options that configure the behavior of the widget (which store views, which order statuses, and so on). The expected shape is documented in Configurable Inputs.
The default implementation should be:
getDisplayProperties()
Returns the input options that configure the appearance of the widget. Same shape and default implementation pattern
as getConfigurableProperties().
getTrailingAction()
public function getTrailingAction(WidgetContextInterface $ctx, ?WidgetInstanceInterface $widgetInstance): array
Returns the link rendered at the bottom of the widget card (typically a "View all" action). The default implementation
should be return $ctx->getTrailingAction();. The framework reads the
<trailing_action> element from the widget XML and exposes it through $ctx.
isAllowed()
public function isAllowed(WidgetContextInterface $ctx, ?WidgetInstanceInterface $widgetInstance): bool
Custom permission logic. The default $ctx->isAllowed($widgetInstance) implementation returns false when the current
admin user does not have access to the resource defined in the widget's <acl> XML configuration, or
when the widget instance was created by another admin user.
beforeSave() / afterSave()
public function beforeSave(WidgetContextInterface $ctx, WidgetInstanceInterface $widgetInstance): WidgetInstanceInterface
public function afterSave(WidgetContextInterface $ctx, WidgetInstanceInterface $widgetInstance): WidgetInstanceInterface
Intercept the save lifecycle of a widget instance. Both must return a WidgetInstanceInterface, typically the same
instance passed in. These methods are invoked by
Hyva\AdminDashboardFramework\Model\WidgetInstance\WidgetInstanceRepository::save().
Tip
The Checklist, Links, and Google CrUX History widgets are good examples of where these hooks are used to
transform configuration values or trigger external data fetches.
Registering the Widget
Widgets are registered in etc/adminhtml/hyva_dashboard_widget.xml. See XML Configuration for the full
reference; the schema lives in the Hyva_AdminDashboardApi module:
urn:magento:module:Hyva_AdminDashboardApi:etc/adminhtml/hyva_dashboard_widget.xsd.
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Hyva_AdminDashboardApi:etc/adminhtml/hyva_dashboard_widget.xsd">
<widget id="order_volume">
<title>Order Volume</title>
<class>Acme\OrderVolumeWidget\Model\Widget\OrderVolume</class>
<display_type>bar_chart</display_type>
<category>sales</category>
<icon>chart-column</icon>
<min_height>6</min_height>
<min_width>2</min_width>
</widget>
</config>
Related Topics
- XML Configuration - The full
hyva_dashboard_widget.xmlreference for registering a widget type. - Configurable Inputs - The shape of the arrays returned by
getConfigurableProperties()andgetDisplayProperties(). - Available Widget Types - The widget types bundled with the dashboard.
- Widget PHP Implementation (Legacy API) - The pre-
2.0.0inheritance-based contract.