I need to add dynamic rows into the custom-made-widget, without uiComponent. I have a system.xml with the block:

<section id="general" type="text">
   <group id="quantity_ranges" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
       <label>Quantity Ranges</label>
         <field id="ranges" translate="label" sortOrder="0" showInDefault="1" showInWebsite="1" showInStore="1">

and the Block: Vendor\module\Block\Adminhtml\Form\Field\DynamicRows

class DynamicRows extends AbstractFieldArray
    public function _prepareToRender()
        $this->addColumn('sku', ['label' => __('Sku'), 'class' => 'required-entry']);
        $this->addColumn('position', ['label' => __('Position'), 'class' => 'required-entry']);

        $this->_addAfter = false;
        $this->_addButtonLabel = __('Add');

and it works. BUT, I need this into the widget, which does NOT work:

<parameter name="hotspots" xsi:type="block" required="false" visible="true">
  <label translate="true">Hotspots products</label>
  <block class="Vendor\Module\Block\Adminhtml\Form\Field\Hospot" />

block: \Vendor\Module\Block\Adminhtml\Form\Field\Hospot

class Hospot extends Template
    public function prepareElementHtml(AbstractElement $element): AbstractElement
        // Create the dynamics rows
        $dynamicRows = $this->getLayout()->createBlock(AbstractFieldArray::class);
        $dynamicRows->addColumn('label', ['label' => __('Sku')]);
        $dynamicRows->addColumn('position', ['label' => __('Position')]);

        $element->setData('after_element_html', $dynamicRows->toHtml() . "<script>require(['mage/adminhtml/browser']);</script>");

        return $element;

Has anyone had faced this particular case?

2 Answers 2


In your new Vendor\Module\Block\Adminhtml\Form\Field\Hospot class you're trying to create a block from an abstract class. This is not possible. Instead, you should use a separate class that is instantiated from the given abstract class. And additionally, you have to set an $element for this new class. So here is how your Vendor\Module\Block\Adminhtml\Form\Field\Hospot class should look like:


namespace Vendor\Module\Block\Adminhtml\Form\Field;

use Magento\Framework\Data\Form\Element\AbstractElement;
use Magento\Framework\View\Element\Template;

class Hotspot extends Template
    public function prepareElementHtml(AbstractElement $element)
        $dynamicRows = $this->getLayout()

        $element->setData('after_element_html', $dynamicRows->toHtml() . "<script>require(['mage/adminhtml/browser']);</script>");

        return $element;

BUT! When trying to save the widget you will be getting an error. Because in Magento\Widget\Model\Widget::getDirectiveParam() Magento tries to implode the array of the widget settings. And since the dynamic rows value is a multi-level array, it cannot be converted to a string using the implode() function. So probably you will need to add a couple of class plugins to convert the value to a string.

  • Yesssss! It works!!! It's exactley what i need it. Thanks a lot @MagestyApps
    – AcidBurn
    Nov 18, 2021 at 10:56

@AcidBurn, could you share the answer to the saving problem? This is an ideal solution to a widget I'm building, but I'm having trouble saving the widget as @MagestryApps already predicted.

  • This is not answer to the question. Please add it as a comment to MagestyApps answer May 19 at 9:35
  • I have created a custom table and saved the post data (widget data, with a Controller) in the database. But you can, also, just save the widget data and it will be saved in the Widget instance.
    – AcidBurn
    May 26 at 11:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.