Implement new widget 

New in version 14.0

Each extension can provide multiple Widgets. ext:dashboard already ships with some widget implementations.

Each widget has to be implemented as a PHP class. The PHP class defines the concrete implementation and features of a widget, while registration adds necessary options for a concrete instance of a widget.

For example a TYPO3.org RSS Widget would consist of an RssWidget PHP class. This class would provide the implementation to fetch rss news and display them. The concrete registration will provide the URL to RSS feed.

PHP class 

Each Widget has to be a PHP class. This class should implement the WidgetRendererInterface and could look like this:

class RssWidget implements WidgetRendererInterface
{
    public function __construct(
        private readonly WidgetConfigurationInterface $configuration,
        private readonly FrontendInterface $cache,
        private readonly BackendViewFactory $backendViewFactory,
        private readonly ?ButtonProviderInterface $buttonProvider = null,
        private readonly array $options = []
    ) {
    }

    public function getSettingsDefinitions(): array
    {
        return [];
    }

    public function renderWidget(WidgetContext $context): WidgetResult
    {
        $view = $this->backendViewFactory->create($context->request);
        $view->assignMultiple([
            'items' => $this->getRssItems(),
            'options' => $this->options,
            'button' => $this->getButton(),
            'configuration' => $this->configuration,
        ]);
        return new WidgetResult(
            content: $view->render('Widget/RssWidget'),
            refreshable: $this->options['refreshAvailable'] ?? false,
        );
    }

    protected function getRssItems(): array
    {
        $items = [];
        // Logic to populate $items array
        return $items;
    }
}
Copied!

The class should always provide documentation how to use in Services.yaml. The above class is documented at RSS Widget. The documentation should provide all possible options and an concrete example. It should make it possible for integrators to register new widgets using the implementation.

The difference between $options and $configuration in above example is the following: $options are the options for this implementation which can be provided through Services.yaml. $configuration is an instance of WidgetConfigurationInterface holding all internal configuration, like icon identifier.

Using Fluid 

Most widgets will need a template. Therefore each widget can define BackendViewFactory as requirement for DI in constructor, like done in RSS example.

Providing custom JS 

There are two ways to add JavaScript for an widget:

JavaScript module

Implement \TYPO3\CMS\Dashboard\Widgets\JavaScriptInterface :

class ExampleChartWidget implements JavaScriptInterface
{
    // ...
    public function getJavaScriptModuleInstructions(): array
    {
        return [
            JavaScriptModuleInstruction::create(
                '@myvendor/my-extension/module-name.js'
            )->invoke('initialize'),
            JavaScriptModuleInstruction::create(
                '@myvendor/my-extension/module-name2.js'
            )->invoke('initialize'),
        ];
    }
}
Copied!
Plain JS files

Implement AdditionalJavaScriptInterface :

class RssWidget implements WidgetInterface, AdditionalJavaScriptInterface
{
    public function getJsFiles(): array
    {
        return [
            'EXT:my_extension/Resources/Public/JavaScript/file.js',
            'EXT:my_extension/Resources/Public/JavaScript/file2.js',
        ];
    }
}
Copied!
JavaScript

Implement \TYPO3\CMS\Dashboard\Widgets\JavaScriptInterface :

class ExampleChartWidget implements JavaScriptInterface
{
    // ...
    public function getJavaScriptModuleInstructions(): array
    {
        return [
            JavaScriptModuleInstruction::create(
                '@typo3/dashboard/chart-initializer.js'
            )->invoke('initialize'),
        ];
    }
}
Copied!

All ways can be combined.

Providing custom CSS 

It is possible to add custom Css to style widgets.

Implement AdditionalCssInterface :

class RssWidget implements WidgetInterface, AdditionalCssInterface
{
      public function getCssFiles(): array
      {
         return [
             'EXT:my_extension/Resources/Public/Css/widgets.css',
             'EXT:my_extension/Resources/Public/Css/list-widget.css',
         ];
      }
}
Copied!