9

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.
3

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

| improve this answer | |
2

I used the following code to create attribute in InstallData.php.

Vendor\Extension\Setup\InstallData.php

<?php
namespace Vendor\Extension\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;

    public function __construct(EavSetupFactory $eavSetupFactory)
    {
        $this->eavSetupFactory = $eavSetupFactory;
    }

    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

        //Category Attribute Create Script
        $eavSetup->addAttribute(
            \Magento\Catalog\Model\Category::ENTITY,
            'attribute_id',
            [
                'group' => 'Mygroup',
                'label' => 'Attribute Label',
                'type'  => 'int',
                'input' => 'boolean',
                'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
                'source' => '',
                'required' => false,
                'sort_order' => 1,
                'global' => \Magento\Catalog\Model\ResourceModel\Eav\Attribute::SCOPE_STORE,
                'used_in_product_listing' => true,
                'visible_on_front' => false
            ]
        );

        $setup->endSetup();
    }
}

And Then I create a file category_form.xml

Vendor\Extension\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="attribute_id">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="label" xsi:type="string" translate="true">Attribute Label</item>
                <item name="collapsible" xsi:type="boolean">true</item>
                <item name="sortOrder" xsi:type="number">25</item>
            </item>
        </argument>
        <field name="attribute_id">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="sortOrder" xsi:type="number">20</item>
                    <item name="dataType" xsi:type="string">boolean</item>
                    <item name="formElement" xsi:type="string">checkbox</item>
                    <item name="source" xsi:type="string">category</item>
                    <item name="prefer" xsi:type="string">toggle</item>
                    <item name="valueMap" xsi:type="array">
                        <item name="true" xsi:type="string">1</item>
                        <item name="false" xsi:type="string">0</item>
                    </item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">false</item>
                    </item>
                    <item name="default" xsi:type="string">0</item>
                    <item name="label" xsi:type="string" translate="true">Attribute Label</item>
                </item>
            </argument>
        </field>
</form>
| 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.