I need to show category tree, just like in admin section, in my custom page. I viewed this solution in magento.stackexchange.com. It was good but limited to 2 levels of category. I need all the categories. How can it be done?
4 Answers
I searched over internet for solution to this but got nothing useful. Then I diverted my research towards Magento core where I found \Magento\Catalog\Block\Adminhtml\Category\Tree class where I found a function getTree(). Then I tried to observed it's return value in my custom template file. The effort became fruitful as I got the desired result.
I created a block file where I have injected the above class as:
<?php
namespace Vendor\Module\Block;
class CategoriesColle extends \Magento\Framework\View\Element\Template
{
...
protected $adminCategoryTree;
/**
* @param \Magento\Framework\View\Element\Template\Context $context
* @param \Magento\Catalog\Helper\Category $categoryHelper
* @param array $data
*/
public function __construct(
...
\Magento\Catalog\Block\Adminhtml\Category\Tree $adminCategoryTree
)
{
...
$this->adminCategoryTree = $adminCategoryTree;
}
public function getTree()
{
return $this->adminCategoryTree->getTree();
}
...
}
The return value of the getTree() is the desired array of the category tree which can be verified by dumping the value in template file.
-
-
you can use in layout by block class="vendor/module/block/CategoriesColle" template="Vendor_Module:yourcustomphtml.phtml" Jul 19, 2019 at 6:33
You can create your own tree with custom collection as follows: Firstly add a field in your ui-form:
<field name="custom" component="Namespce_Modulename/js/select-category" sortOrder="20" formElement="select">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="filterOptions" xsi:type="boolean">true</item>//to add filter in select-ui
<item name="multiple" xsi:type="boolean">false</item>//select multiple or not
<item name="showCheckbox" xsi:type="boolean">true</item>//to show checkboxes
<item name="disableLabel" xsi:type="boolean">true</item>
</item>
</argument>
<settings>
<required>true</required>
<validation>
<rule name="required-entry" xsi:type="boolean">true</rule>
</validation>
<elementTmpl>ui/grid/filters/elements/ui-select</elementTmpl>
<label translate="true">Select Category</label>//label to Field
<dataScope>data.custom</dataScope>//To map
<componentType>field</componentType>
<listens>
<link name="${ $.namespace }.${ $.namespace }:responseData">setParsed</link>
</listens>
</settings>
<formElements>
<select>
<settings>
<options class="Namespace\ModuleName\Ui\Component\Form\Category\Options"/>
</settings>
</select>
</formElements>
Now create Js file to map the field's value:
Namespace_Modulename/view/adminhtml/web/js/select-category.js
define([
'Magento_Ui/js/form/element/ui-select'
], function (Select) {
'use strict';
return Select.extend({
/**
* Parse data and set it to options.
*
* @param {Object} data - Response data object.
* @returns {Object}
*/
setParsed: function (data) {
var option = this.parseData(data);
if (data.error) {
return this;
}
this.options([]);
this.setOption(option);
this.set('newOption', option);
},
/**
* Normalize option object.
*
* @param {Object} data - Option object.
* @returns {Object}
*/
parseData: function (data) {
return {
value: data.category.entity_id,
label: data.category.name
};
}
});
});
Create a file to get options to display:
Namespace\ModuleName\Ui\Component\Form\Category\Options.php
<?php
namespace Namespace\ModuleName\Ui\Component\Form\Category;
use Magento\Framework\Data\OptionSourceInterface;
use Magento\Category\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory;
use Magento\Framework\App\RequestInterface;
/**
* Options tree for "Categories" field
*/
class Options implements OptionSourceInterface
{
protected $categoryCollectionFactory;
/**
* @var RequestInterface
*/
protected $request;
/**
* @var array
*/
protected $categoryTree;
/**
* @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->getCategoryTree();
}
/**
* Retrieve categories tree
*
* @return array
*/
protected function getCategoryTree()
{
if ($this->categoryTree === null) {
$collection = $this->categoryCollectionFactory->create();
$collection->addNameToSelect();
foreach ($collection as $category) {
$categoryId = $category->getEntityId();
if (!isset($categoryById[$categoryId])) {
$categoryById[$categoryId] = [
'value' => $categoryId
];
}
$categoryById[$categoryId]['label'] = $category->getName();
}
$this->categoryTree = $categoryById;
}
return $this->categoryTree;
}
}
Hope it helps!
-
-
-
yes @user00247 i have followed your steps, can see steps here magento.stackexchange.com/questions/249360/… Nov 9, 2018 at 8:56
$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); //$category = $objectManager->create('Magento\Catalog\Model\Category') //Magento\Customer\Model\ResourceModel\Customer\CollectionFactory $category = $objectManager->create('Magento\Catalog\Model\ResourceModel\Category\CollectionFactory')->create() ->addAttributeToSelect('entity_id') ->addAttributeToSelect('name') ->addAttributeToSelect('parent_id') ->addAttributeToSelect('url_path') ->addAttributeToSelect('request_path') ->addAttributeToSelect('include_in_menu') //->addAttributeToSelect('*') ->addAttributeToFilter('level',array('nin' => array(1))) ->addAttributeToFilter('path',array('like' => '%'.$rootCategoryId.'%')) ->addAttributeToSort('parent_id', 'ASC') ->addAttributeToSort('position', 'ASC') ->addAttributeToSort('path', 'ASC'); // print_r($category->getData()); $catArray = []; foreach ($category as $cat){ $catArray[$cat->getID()]['id']= $cat->getID(); $catArray[$cat->getID()]['name'] = $cat->getName(); $catArray[$cat->getID()]['parent_id'] = $cat->getParentId(); $catArray[$cat->getID()]['position'] = $cat->getPosition(); $catArray[$cat->getID()]['path'] = $cat->getPath(); } print_r($catArray);
// Get all the children categories of given category collection factory
foreach ($collection as $key => $value) {
$temp = $value->getData();
$categoryObj = $this->_repository->get($temp['entity_id']);
$subcategories = $categoryObj->getChildrenCategories();
foreach($subcategories as $key2 => $subcategory) {
if($subcategory->hasChildren()) {
$childCategoryObj = $this->_repository->get($subcategory->getId());
$childSubcategories = $childCategoryObj->getChildrenCategories();
foreach($childSubcategories as $childSubcategory) {
$temp2 = $childSubcategory->getData();
$temp1['children'][] = $temp2;
}
$temp['children'][] = $temp1;
}
}
$item[$key][] = $temp;
}
// Here you can get all the children upto 2 level in "item" variable
echo "<pre>";
print_r($item);