Magento – Magento 2 :- Add select attribute to category

attributescategorymagento2setup-script

I want to add a select/dropdown attribute to a category and display it in the backend to let the store owner select it. After some research I found out the following to do:

  • Create an attribute via Setupscript
  • Include it via UI component declaration

So this is what I have done:

public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
    /** @var $eavSetup \Magento\Eav\Setup\EavSetup */
    $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

    $eavSetup->addAttribute(
        \Magento\Catalog\Model\Category::ENTITY,
        'attribute_code',
        [
            'type' => 'int',
            'label' => 'Top Navigation CMS Block',
            'input' => 'select',
            'source' => 'Magento\Catalog\Model\Category\Attribute\Source\Page',
            'required' => false,
            'sort_order' => 10,
            'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
            'group' => 'MyOwnGroup'
        ]
    );
}

view/adminhtml/ui_component/category_form.xml:

<?xml version="1.0" encoding="UTF-8"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="content">
        <field name="attribute_code">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="sortOrder" xsi:type="number">61</item>
                    <item name="dataType" xsi:type="string">string</item>
                    <item name="formElement" xsi:type="string">select</item>
                    <item name="label" xsi:type="string" translate="true">Top Navigation CMS Block</item>
                </item>
            </argument>
        </field>
    </fieldset>
</form>

But that is not enough, the sorting of the tabs in the backend is mixed up. Also the dropdown gets rendered, but without options. So I found out that you also have to edit Magento\Catalog\Model\Category\DataProvider::getFieldsMap(). In order to do that we have to overwrite it via di.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Catalog\Model\Category\DataProvider" type="Vendor\Module\Model\Category\DataProvider" />
</config>

In the module's own data provider you have to add the attribute in the function. And then it works.

So here are my questions:

  • I don't think that you really have to overwrite this data provider to make it work, there must be a better way
  • There are 3 places inside the code where you have to declare the new attribute (setup script, ui component, data provider), I can't believe that this much overhead is necessary?
  • Why do you have redundant information for the attribute? For example the label is inside the setup script AND the ui component where as the label in the backend will be read from the ui component declaration.

Best Answer

You need to add an node "options" to ui-component config

<field name="roflcopter">
    <argument name="data" xsi:type="array">
        <item name="options" xsi:type="object">Magento\Catalog\Model\Category\Attribute\Source\Page</item>
        <item name="config" xsi:type="array">
            <item name="sortOrder" xsi:type="number">70</item>
            <item name="dataType" xsi:type="string">string</item>
            <item name="formElement" xsi:type="string">select</item>
            <item name="label" xsi:type="string" translate="true">Roflcopter</item>
        </item>
    </argument>
</field>

taken from here Magento2.1 Category custom attribute dropdown