1

In Magento 2, I want to add multiselect UI dropdown with custom my custom array.

I take reference from product edit form "Categories" field and also find out from where UI multiselect tree option added.

vendor/magento/module-catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php

From this file, customizeCategoriesField() function set UI multiselect dropdown by $this->getCategoriesTree() this line.

But, how can I implement in my custom form?

enter image description here

Any help would be appriciated.

1 Answer 1

3

You can add below code for to add in your UI XML file:

 <field name="category_id">
        <argument name="data" xsi:type="array">
            <item name="options" xsi:type="object">Namespace\VendorName\Model\Source\CategoryTree</item>
            <item name="config" xsi:type="array">
                <item name="label" xsi:type="string" translate="true">Category</item>
                <item name="componentType" xsi:type="string">field</item>
                <item name="formElement" xsi:type="string">multiselect</item>
                <item name="component" xsi:type="string">Magento_Ui/js/form/element/ui-select</item>
                <item name="elementTmpl" xsi:type="string">ui/grid/filters/elements/ui-select</item>
                <item name="dataScope" xsi:type="string">category_id</item>
                <item name="filterOptions" xsi:type="boolean">true</item>
                <item name="showCheckbox" xsi:type="boolean">true</item>
                <item name="disableLabel" xsi:type="boolean">true</item>
                <item name="sortOrder" xsi:type="number">60</item>
                <item name="multiple" xsi:type="boolean">true</item>
                <item name="levelsVisibility" xsi:type="number">0</item>
                <item name="required" xsi:type="boolean">true</item>
                <item name="source" xsi:type="string">sourceName</item>
                <item name="validation" xsi:type="array">
                    <item name="required-entry" xsi:type="boolean">false</item>
                </item>
                <item name="listens" xsi:type="array">
                    <item name="${ $.namespace }.${ $.namespace }:responseData" xsi:type="string">setParsed</item>
                </item>
            </item>
        </argument>
    </field>

Then add below code of Source Model of Category Tree:

<?php

namespace namespace\vendorName\Model\Source;

use Magento\Framework\Data\OptionSourceInterface;
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory;
use Magento\Framework\App\RequestInterface;
use Magento\Catalog\Model\Category as CategoryModel;

/**
 * Options tree for "Categories" field
 */
class CategoryTree implements OptionSourceInterface
{
    /**
     * @var \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory
     */
    protected $categoryCollectionFactory;

    /**
     * @var RequestInterface
     */
    protected $request;

    /**
     * @var array
     */
    protected $categoriesTree;

    /**
     * @param CategoryCollectionFactory $categoryCollectionFactory
     * @param RequestInterface $request
     */
    public function __construct(
        CategoryCollectionFactory $categoryCollectionFactory,
        RequestInterface $request
    ) {
        $this->categoryCollectionFactory = $categoryCollectionFactory;
        $this->request = $request;
    }

    /**
     * {@inheritdoc}
     */
    public function toOptionArray()
    {
        return $this->getCategoriesTree();
    }

    /**
     * Retrieve categories tree
     *
     * @return array
     */
    protected function getCategoriesTree()
    {
        if ($this->categoriesTree === null) {
            $storeId = $this->request->getParam('store');
            /* @var $matchingNamesCollection \Magento\Catalog\Model\ResourceModel\Category\Collection */
            $matchingNamesCollection = $this->categoryCollectionFactory->create();

            $matchingNamesCollection->addAttributeToSelect('path')
                ->addAttributeToFilter('entity_id', ['neq' => CategoryModel::TREE_ROOT_ID])
                ->setStoreId($storeId);

            $shownCategoriesIds = [];

            /** @var \Magento\Catalog\Model\Category $category */
            foreach ($matchingNamesCollection as $category) {
                foreach (explode('/', $category->getPath()) as $parentId) {
                    $shownCategoriesIds[$parentId] = 1;
                }
            }

            /* @var $collection \Magento\Catalog\Model\ResourceModel\Category\Collection */
            $collection = $this->categoryCollectionFactory->create();

            $collection->addAttributeToFilter('entity_id', ['in' => array_keys($shownCategoriesIds)])
                ->addAttributeToSelect(['name', 'is_active', 'parent_id'])
                ->setStoreId($storeId);

            $categoryById = [
                CategoryModel::TREE_ROOT_ID => [
                    'value' => CategoryModel::TREE_ROOT_ID
                ],
            ];
            foreach ($collection as $category) {
                if ( $category->getData('level') <= 2 ) {
                    foreach ([$category->getId(), $category->getParentId()] as $categoryId) {
                        if ( !isset($categoryById[$categoryId]) ) {
                            $categoryById[$categoryId] = ['value' => $categoryId];
                        }
                    }
                    $categoryById[$category->getId()]['is_active'] = $category->getIsActive();
                    $categoryById[$category->getId()]['label'] = $category->getName();
                    $categoryById[$category->getParentId()]['optgroup'][] = &$categoryById[$category->getId()];
                }
            }
            $this->categoriesTree = $categoryById[CategoryModel::TREE_ROOT_ID]['optgroup'];
        }

        return $this->categoriesTree;
    }
}
3
  • Hi getting error "Call to a member function getData() on null" , after implementing your code. Commented Dec 7, 2020 at 5:24
  • This is working fine for 2.2.X version Commented Dec 8, 2020 at 11:40
  • could you please check my question magento.stackexchange.com/q/327671/24878 Commented Dec 9, 2020 at 9:07

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.