3

How to add below in my custom widget.xml?

enter image description here

below code does not have possibility of multiple products selection :(

<parameter name="id_path" xsi:type="block" visible="true" required="true" sort_order="10">
                <label translate="true">Product</label>
                <block class="Magento\Catalog\Block\Adminhtml\Product\Widget\Chooser">
                    <data>
                        <item name="button" xsi:type="array">
                            <item name="open" xsi:type="string">Select Product...</item>
                        </item>
                    </data>
                </block>
</parameter>

1 Answer 1

4

The solution ;)

In widget.xml of the custom module:

<parameter name="multi_product_chooser" xsi:type="block" visible="true" required="true" sort_order="10">
      <label translate="true">Select Products</label>
      <block class="MyVendor\MyModule\Block\Chooser" />
</parameter>

and Chooser block like below:

<?php
namespace MyVendor\MyModule\Block;

class Chooser extends \Magento\Backend\Block\Template
{

    protected $_elementFactory;

    /**
     * @param \Magento\Backend\Block\Template\Context $context
     * @param \Magento\Framework\Data\Form\Element\Factory $elementFactory
     * @param array $data
     */
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Framework\Data\Form\Element\Factory $elementFactory, array $data = []
    )
    {
        $this->_elementFactory = $elementFactory;
        parent::__construct($context, $data);
    }

    /**
     * Prepare chooser element HTML
     *
     * @param \Magento\Framework\Data\Form\Element\AbstractElement $element Form Element
     * @return \Magento\Framework\Data\Form\Element\AbstractElement
     */
    public function prepareElementHtml(\Magento\Framework\Data\Form\Element\AbstractElement $element)
    {
        $htmlId = $element->getId();
        $data = $element->getData();

        $data['after_element_js'] = $this->_afterElementJs($element);
        $data['after_element_html'] = $this->_afterElementHtml($element);
        $data['readonly'] = 'readonly';
        $htmlItem = $this->_elementFactory->create('text', ['data' => $data]);
        $htmlItem
            ->setId("{$htmlId}")
            ->setForm($element->getForm())
            ->addClass('required-entry')
            ->addClass('entities');
        $return = <<<HTML
                <div id="{$htmlId}-container" class="chooser_container">{$htmlItem->getElementHtml()}</div>
HTML;
        $element->setData('after_element_html', $return);
        return $element;
    }

    protected function _afterElementHtml($element)
    {
        $htmlId = $element->getId();
        $return = <<<HTML
            <a href="javascript:void(0)" onclick="MultiProductChooser.displayChooser('{$htmlId}-container')" class="widget-option-chooser" title="{__('Open Chooser')}">
                <img src="{$this->getViewFileUrl('images/rule_chooser_trigger.gif')}" alt="{__('Open Chooser')}" />
            </a>
            <a href="javascript:void(0)" onclick="MultiProductChooser.hideChooser('{$htmlId}-container')" title="{__('Apply')}">
                <img src="{$this->getViewFileUrl('images/rule_component_apply.gif')}" alt="{__('Apply')}">
            </a>
            <div class="chooser skuchooser"></div>
HTML;
        return $return;
    }

    protected function _afterElementJs($element)
    {
        $chooserUrl = $this->getUrl('adminhtml/widget_instance/products', []);
        $htmlId = $element->getId();
        $return = <<<HTML
            <script>
                    require([
                    'jquery',
                    'Magento_Ui/js/modal/alert',
                    "prototype"
                ], function (jQuery, alert) {
                    var MultiProductChooser = {
                        displayChooser : function(chooser) {
                            chooser  = $(chooser).down('div.chooser');
                            entities = chooser.up('div.chooser_container').down('input[type="text"].entities').value;
                            postParameters = {selected: entities};
                            url = '{$chooserUrl}';
                            if (chooser && url) {
                                if (chooser.innerHTML == '') {
                                        new Ajax.Request(url, {
                                        method  : 'post',
                                        parameters : postParameters,
                                        onSuccess  : function(transport) {
                                            try {
                                                if (transport.responseText) {
                                                    Element.insert(chooser, transport.responseText);
                                                    chooser.removeClassName('no-display');
                                                    chooser.show();
                                                }
                                            } catch (e) {
                                                alert({
                                                   content: 'Error occurs during loading chooser.'
                                                });
                                            }
                                        }
                                    });
                                } else {
                                    chooser.removeClassName('no-display');
                                    chooser.show();
                                }
                            }
                       },
                        hideChooser : function(chooser) {
                                chooser = $(chooser).down('div.chooser');
                                if (chooser) {
                                chooser.addClassName('no-display');
                                chooser.hide();
                                }
                        },
                        addProductItemToSelection: function(groupId, item) {
                            if (!isNaN(parseInt(item))) {
                                this.selectedItems[groupId].set(item, 1);
                            }
                        },
                        checkProduct : function(event) {                            
                            var cont = document.querySelector(".skuchooser");
                            var elm = event.memo.element,
                            container = event.target.up('div.chooser').up('div.chooser_container');
                            var matches = cont.querySelector("tr.on-mouse");
                            var mat = matches.querySelector("td.col-chooser_sku");                          
                            value = container.down('input[type="text"].entities').value.strip();
                            pickedSku = mat.childNodes[0].nodeValue;                 
                            pickedSku = pickedSku.trim();
                            if (elm.checked) {
                                if (value) ids = value.split(',');
                                else ids = [];

                                if (-1 == ids.indexOf(pickedSku)) {
                                    ids.push(pickedSku);
                                    container.down('input[type="text"].entities').value = ids.join(',');
                                }
                            } else {
                                ids = value.split(',');

                                while (-1 != ids.indexOf(pickedSku)) {
                                    ids.splice(ids.indexOf(pickedSku), 1);
                                    container.down('input[type="text"].entities').value = ids.join(',');
                                }
                            }                          
                          }
                      }
                    window.MultiProductChooser = MultiProductChooser;
                    jQuery(function() {
                        var container = $('{$htmlId}-container');
                        if (container) {
                            container.up(0).down('.control-value').hide();
                        }              
                         Event.observe(document, 'product:changed', function(event){
                            MultiProductChooser.checkProduct(event);
                        });
                        Event.observe(document, 'category:beforeLoad', function(event) {
                                container = event.target.up('div.chooser_container');
                                value   = container.down('input[type="text"].entities').value.strip();
                            event.memo.treeLoader.baseParams.selected = value;
                        });
                    });
                });
            </script>
HTML;
        return $return;
    }
}
1
  • Hello @Zinat, I have list of sku, can we create widget dynamically and load the products in list manner.. Commented Jul 15, 2019 at 7:44

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.