Magento2 : Create multi select category attribute with custom source. Can anyone give me with example?
3 Answers
For a mult select attribute, you can need to add below at your installer:
source model:
[VendorName]\[ModuleName]\Model\Category\Attribute\Source\Custom.php
backend Model
[VendorName]\[ModuleName]\Model\Category\Attribute\Backend\Custom.php
- input_renderer for admin html area
[VendorName]\[ModuleName]\Block\Adminhtml\Category\Helper\Custom\Options.php
Install file[app/code/[VendorName]/[ModuleName]/Setup/InstallData.php
] an code:
<?php
namespace [VendorName]\[ModuleName]\Setup;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
class InstallData implements InstallDataInterface
{
private $eavSetupFactory;
/**
* Init
*
* @param EavSetupFactory $eavSetupFactory
*/
public function __construct(EavSetupFactory $eavSetupFactory)
{
$this->eavSetupFactory = $eavSetupFactory;
}
/**
* {@inheritdoc}
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
/** @var EavSetup $eavSetup */
$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
/**
* Add attributes to the eav/attribute
*/
$eavSetup->addAttribute(
\Magento\Catalog\Model\Category::ENTITY,
'multi_custom_attribute',
[
'type' => 'text',
'label' => 'Custom Attribute Description',
'input' => 'multiselect',
'required' => false,
'source' => '[VendorName]\[ModuleName]\Model\Category\Attribute\Source\Custom',
'backend' => '[VendorName]\[ModuleName]\Model\Category\Attribute\Backend\Custom',
'input_renderer' => '[VendorName]\[ModuleName]\Block\Adminhtml\Category\Helper\Custom\Options',
'sort_order' => 100,
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
'group' => 'General Information',
'is_used_in_grid' => true,
'is_visible_in_grid' => false,
'is_filterable_in_grid' => true,
]
);
}
}
Source model:
location: app\code\[VendorName]\[ModuleName]\Model\Category\Attribute\Source\Custom.php
code:
<?php
namespace [VendorName]\[ModuleName]\Model\Category\Attribute\Source;
class Custom extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
{
/**
* Catalog config
*
* @var \Magento\Catalog\Model\Config
*/
protected $_catalogConfig;
/**
* Construct
*
* @param \Magento\Catalog\Model\Config $catalogConfig
*/
public function __construct(\Magento\Catalog\Model\Config $catalogConfig)
{
$this->_catalogConfig = $catalogConfig;
}
/**
* Retrieve Catalog Config Singleton
*
* @return \Magento\Catalog\Model\Config
*/
protected function _getCatalogConfig()
{
return $this->_catalogConfig;
}
/**
* {@inheritdoc}
*/
public function getAllOptions()
{
if ($this->_options === null) {
$this->_options = [
['label' => __('Label1'), 'value' => 'value1'],
['label' => __('Label2'), 'value' => 'value2'],
['label' => __('Label3'), 'value' => 'value3'],
['label' => __('Label4'), 'value' => 'value4']
];
}
return $this->_options;
}
}
backend model:
location: [VendorName]\[ModuleName]\Model\Category\Attribute\Backend\Custom.php
code:
<?php
namespace [VendorName]\[ModuleName]\Model\Category\Attribute\Backend;
class Custom extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
{
/**
* Core store config
*
* @var \Magento\Framework\App\Config\ScopeConfigInterface
*/
protected $_scopeConfig;
/**
* Construct
*
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
*/
public function __construct(\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig)
{
$this->_scopeConfig = $scopeConfig;
}
/**
* Validate process
*
* @param \Magento\Framework\DataObject $object
* @return bool
* @throws \Magento\Framework\Exception\LocalizedException
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
/**
* Before Attribute Save Process
*
* @param \Magento\Framework\DataObject $object
* @return $this
*/
public function beforeSave($object)
{
$attributeCode = $this->getAttribute()->getName();
if ($attributeCode == 'multi_custom_attribute') {
$data = $object->getData($attributeCode);
if (!is_array($data)) {
$data = [];
}
$object->setData($attributeCode, implode(',', $data) ?: null);
}
if (!$object->hasData($attributeCode)) {
$object->setData($attributeCode, null);
}
return $this;
}
/**
* After Load Attribute Process
*
* @param \Magento\Framework\DataObject $object
* @return $this
*/
public function afterLoad($object)
{
$attributeCode = $this->getAttribute()->getName();
if ($attributeCode == 'multi_custom_attribute') {
$data = $object->getData($attributeCode);
if ($data) {
if (!is_array($data)) {
$object->setData($attributeCode, explode(',', $data));
} else {
$object->setData($attributeCode, $data);
}
}
}
return $this;
}
}
input_renderer for admin html area:
location: [VendorName]\[ModuleName]\Block\Adminhtml\Category\Helper\Custom\Options.php
code:
<?php
namespace [VendorName]\[ModuleName]\Block\Adminhtml\Category\Helper\Custom;
class Options extends \Magento\Framework\Data\Form\Element\Multiselect
{
/**
* Returns js code that is used instead of default toggle code for "Use default config" checkbox
*
* @return string
*/
public function getToggleCode()
{
$htmlId = 'use_config_' . $this->getHtmlId();
return "toggleValueElements(this, this.parentNode.parentNode);" .
"if (!this.checked) toggleValueElements(\$('{$htmlId}'), \$('{$htmlId}').parentNode);";
}
/**
* Retrieve Element HTML fragment
*
* @return string
*/
public function getElementHtml()
{
$elementDisabled = $this->getDisabled() == 'disabled';
$disabled = false;
if (!$this->getValue() || $elementDisabled) {
$this->setData('disabled', 'disabled');
$disabled = true;
}
$html = parent::getElementHtml();
$htmlId = 'use_config_' . $this->getHtmlId();
$html .= '<input id="' . $htmlId . '" name="use_config[]" value="' . $this->getId() . '"';
$html .= $disabled ? ' checked="checked"' : '';
if ($this->getReadonly() || $elementDisabled) {
$html .= ' disabled="disabled"';
}
$html .= ' onclick="toggleValueElements(this, this.parentNode);" class="checkbox" type="checkbox" />';
$html .= ' <label for="' . $htmlId . '" class="normal">' . __('Use All Available Attributes') . '</label>';
$html .= '<script>require(["prototype"], function(){toggleValueElements($(\'' .
$htmlId .
'\'), $(\'' .
$htmlId .
'\').parentNode);});</script>';
return $html;
}
}
-
What code I need to put in [VendorName][ModuleName]\view\adminhtml\ui_component\category_form.xml Commented Sep 5, 2016 at 8:58
-
-
-
1thanks @amit bera you have helped me a lot thank you so much Commented Dec 8, 2017 at 12:27
-
This is just an addition to Amits Answer for last step which he has not given.
For admin form you need to create below file.
[VendorName][ModuleName]\view\adminhtml\ui_component\category_form.xml
<?xml version="1.0"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<fieldset name="general">
<field name="multi_custom_attribute">
<argument name="data" xsi:type="array">
<item name="options" xsi:type="object">app\code\[VendorName]\[ModuleName]\Model\Category\Attribute\Source\Custom</item>
<item name="config" xsi:type="array">
<item name="sortOrder" xsi:type="number">60</item>
<item name="dataType" xsi:type="string">string</item>
<item name="formElement" xsi:type="string">multiselect</item>
<item name="label" xsi:type="string" translate="true">Custom Label</item>
</item>
</argument>
</field>
</fieldset>
</form>
@Amit you are great. Hope this helps others.
I have tried to run the above code. Thanks @Amit for sharing this code and @Ashish for adding missing file but there are three corrections in the paths so as to make the code work. Below are the details of the corrections that I have done after which the module worked.
First:
In Install file [app/code/[VendorName]/[ModuleName]/Setup/InstallData.php] code:
Change:
'backend' => '[VendorName]\[ModuleName]\Model\Category\Attribute\Source\Custom',
To:
'backend' => '[VendorName]\[ModuleName]\Model\Category\Attribute\Backend\Custom',
Second:
backend model file location:
Change:
location: [VendorName]\[ModuleName]\Model\Category\Attribute\Source\Custom.php
To:
location: [VendorName]\[ModuleName]\Model\Category\Attribute\Backend\Custom.php
Third Correction is in missing file that @Ashish has shared:
Change:
<item name="options" xsi:type="object">app\code\[VendorName]\[ModuleName]\Model\Category\Attribute\Source\Custom</item>
To:
<item name="options" xsi:type="object">[VendorName]\[ModuleName]\Model\Category\Attribute\Source\Custom</item>
Hope it will help to other user's who were facing the same problem. Thanks.