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.

2

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;
    }
}
| improve this answer | |

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.