2

Is there an easy way to use the Magento\Catalog\Block\Adminhtml\Category\Widget\Chooser in my system.xml file for a field ?

The idea is to be able to pick a category from the chooser widget to store its id as a configuration field.

I don't want to use a simple text input as people will have to find the category id by themselves.

  • Or even a grid view with checkbox (like grid-serializer) can be life saver in such cases. – MagePsycho May 19 '16 at 10:39
  • Are you able to manage this? – MagePsycho Apr 24 '17 at 19:43
  • @MagePsycho nope still haven't found a way – Raphael at Digital Pianism Apr 25 '17 at 6:31
  • Renga I tried to use your solution but checkboxes are not coming. only tree is visible. I am using magento 2.3 – user3243548 Feb 6 '19 at 17:51
5

To Creating A Multiple Category Chooser in Backend:

In your Widget.xml:

<parameter name="multi_category_chooser" xsi:type="block" visible="true" required="true" sort_order="10">
            <label translate="true">Select Categories</label>
            <block class="[Vendor]\[Modul]\Block\Adminhtml\Category\Widget\[Chooser]" />
        </parameter>

Create File : [Vendor][Modul]\Block\Adminhtml\Category\Widget[Chooser]

    <?php
namespace Vendor\Module\Block\Adminhtml\Category\Widget;

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="MultiCategoryChooser.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="MultiCategoryChooser.hideChooser('{$htmlId}-container')" title="{__('Apply')}">
                <img src="{$this->getViewFileUrl('images/rule_component_apply.gif')}" alt="{__('Apply')}">
            </a>
            <div class="chooser"></div>
HTML;
        return $return;
    }

    protected function _afterElementJs($element)
    {
        $chooserUrl = $this->getUrl('adminhtml/widget_instance/categories', []);
        $htmlId     = $element->getId();
        $return = <<<HTML
            <script>
                    require([
                    'jquery',
                    'Magento_Ui/js/modal/alert',
                    "prototype"
                ], function (jQuery, alert) {
                    var MultiCategoryChooser = {
                        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();
                                }
                        },
                        checkCategory : function(event) {
                                node    = event.memo.node;
                                container = event.target.up('div.chooser_container');
                                value   = container.down('input[type="text"].entities').value.strip();
                                if (node.attributes.checked) {
                                if (value) ids = value.split(',');
                                else ids = [];
                                if (-1 == ids.indexOf(node.id)) {
                                    ids.push(node.id);
                                    container.down('input[type="text"].entities').value = ids.join(',');
                                }
                                } else {
                                ids = value.split(',');
                                while (-1 != ids.indexOf(node.id)) {
                                    ids.splice(ids.indexOf(node.id), 1);
                                    container.down('input[type="text"].entities').value = ids.join(',');
                                }
                                }
                        }
                      }
                    window.MultiCategoryChooser = MultiCategoryChooser;
                    jQuery(function() {
                        var container = $('{$htmlId}-container');
                        if (container) {
                            container.up(0).down('.control-value').hide();
                        }

                        Event.observe(document, 'node:changed', function(event){
                            MultiCategoryChooser.checkCategory(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;
    }
}

This is the Multi Category Chooser. enter image description here

| improve this answer | |
  • I need same but your code is not working – Rahul Katoch Jun 20 '18 at 12:53
  • Ok, where you struggled Give more info otherwise I'm helpless. Because it's successfully working for me. – Renga Jun 22 '18 at 7:45
  • Thanks for reply I want to add category chooser in my custom module can you please tell me the code where I ad and get proper category chooser – Rahul Katoch Jun 22 '18 at 12:20
  • Can I use this in custom admin form without ui component? – Sukumar Gorai Mar 22 '19 at 9:21
  • I am getting this error: doesn't extend \Magento\Framework\Data\Form\Element\AbstractElement – Sukumar Gorai Mar 22 '19 at 11:47

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.