Adding an image chooser to a Magento 2 widget

In the previous article we have described how to introduce a new widget in Magento 2. As it was mentioned, each widget field has its own input type. The input type allows determining what graphical interface component will be used to represent this field. Magento 2 has a set of simple input types out of the box such as input field, dropdown etc. Also, it has more complex components: products chooser, rules conditions component, CMS block chooser and others. However, in certain scenarios, you might want to integrate a custom input type, especially if you aim to select images from the media gallery in your widget configuration. In this post we review how to add an image chooser/uploader to your widget.

As a bootstrap we will use the extension we have previously created in the post about adding a widget in Magento 2. For the previously created contact widget we will add an additional field – “photo”. First of all, we need to initialize the new field in the widget.xml file:

…
<parameter name="photo" xsi:type="block" visible="true" sort_order="10">
    <label translate="true">Photo</label>
    <description translate="true">Contact photo</description>

    <block class="Atwix\Widget\Block\Adminhtml\Widget\ImageChooser">
        <data>
            <item name="button" xsi:type="array">
                <item name="open" xsi:type="string">Choose Image...</item>
            </item>
        </data>
    </block>
</parameter>
…

As you can see, the approach for the image chooser field declaration is almost the same as for other widget fields in our module. The only difference is the type of the widget field. We use block type here since we need to add an additional logic to be able to handle the complex graphical component. In the data node we pass some additional arguments, in this case – the button title. Now it’s about time to create the image chooser block:

<?php

namespace Atwix\Widget\Block\Adminhtml\Widget;

use Magento\Framework\Data\Form\Element\AbstractElement as Element;
use Magento\Backend\Block\Template\Context as TemplateContext;
use Magento\Framework\Data\Form\Element\Factory as FormElementFactory;
use Magento\Backend\Block\Template;


class ImageChooser extends Template
{
    /**
     * @var \Magento\Framework\Data\Form\Element\Factory
     */
    protected $elementFactory;

    /**
     * @param TemplateContext $context
     * @param FormElementFactory $elementFactory
     * @param array $data
     */
    public function __construct(
        TemplateContext $context,
        FormElementFactory $elementFactory,
        $data = []
    ) {
        $this->elementFactory = $elementFactory;
        parent::__construct($context, $data);
    }

    /**
     * Prepare chooser element HTML
     *
     * @param Element $element
     * @return Element
     */
    public function prepareElementHtml(Element $element)
    {
        $config = $this->_getData('config');
        $sourceUrl = $this->getUrl('cms/wysiwyg_images/index',
            ['target_element_id' => $element->getId(), 'type' => 'file']);

        /** @var \Magento\Backend\Block\Widget\Button $chooser */
        $chooser = $this->getLayout()->createBlock('Magento\Backend\Block\Widget\Button')
            ->setType('button')
            ->setClass('btn-chooser')
            ->setLabel($config['button']['open'])
            ->setOnClick('MediabrowserUtility.openDialog(\''. $sourceUrl .'\')')
            ->setDisabled($element->getReadonly());

        /** @var \Magento\Framework\Data\Form\Element\Text $input */
        $input = $this->elementFactory->create("text", ['data' => $element->getData()]);
        $input->setId($element->getId());
        $input->setForm($element->getForm());
        $input->setClass("widget-option input-text admin__control-text");
        if ($element->getRequired()) {
            $input->addClass('required-entry');
        }

        $element->setData('after_element_html', $input->getElementHtml() . $chooser->toHtml());

        return $element;
    }
}

In the prepareElementHtml method we create the chooser itself. It’s a simple button created within Magento\Backend\Block\Widget\Button class. For the click event we assign the “MediabrowserUtility.openDialog()” call which opens the standard built-in media chooser window. Next, clean the cache and try to add the contact details widget. If you have followed the instruction accurately, you should have the new field with an ability to choose/upload photos. If you have some troubles with adding an image chooser, you can download the entire widget extension on GitHub.

Also, don’t forget to optimize your images in Magento for enhanced website speed and performance.

Read also: How to import a product image from an URL in Magento

Feel free to leave your ideas and questions in the comments below.

You may also want to read: