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
    Commented Nov 18, 2021 at 10:56
  • i wish you or @AcidBurn posted the full solution, unfortunately this is unusable for the rest of us
    – Robert
    Commented Apr 29 at 12:34

@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 Commented May 19, 2022 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
    Commented May 26, 2022 at 11:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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