Question

I've successfully created several customer extension attributes that display on the customer form and save and load data.
enter image description here

When I try to move these fields to a new custom tab on the customer admin page, they break. The source models still load, but the data isn't populated or saved. I can see when I inspect that the form name changes from customer['my_attribute'] to my_tab[my_attribute].
enter image description here

I suspect I need to change my UpgradeData.php script to use a custom form, but I'm having trouble finding resources on how to go about this.

Relevant snippet from UpgradeData.php:

        $exemptionTypeCode = 'my_exemption_type';
        $eavSetup->addAttribute(
            CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER,
            $exemptionTypeCode,
            [
                'group' => 'General',
                'type' => 'varchar',
                'label' => 'Exemption Type',
                'input' => 'select',

                'required' => false,
                'visible' => true,
                'user_defined' => true,
                'position' => 501,
                'system' => 0,
                'sort_order' => 50,
                'default' => 'non_exempt',

                'source' => 'Custom\Module\Model\Attribute\Source\CustomerExemptionType',
                'backend' => 'Custom\Module\Model\Attribute\Backend\CustomerExemptionType',
                'frontend' => 'Custom\Module\Model\Attribute\Frontend\CustomerExemptionType',
                'global' => 'Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL',

                'is_used_in_grid' => false,
                'is_visible_in_grid' => false,
                'is_filterable_in_grid' => false,
                'is_html_allowed_on_front' => true,
                'visible_on_front' => true
            ]
        );
        $eavSetup->addAttributeToSet(
            CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER,
            CustomerMetadataInterface::ATTRIBUTE_SET_ID_CUSTOMER,
            null,
            $exemptionTypeCode);
        $exemptionType = $this->eavConfig->getAttribute(
            CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER,
            $exemptionTypeCode);
        $exemptionType->setData('used_in_forms', ['adminhtml_customer']);
        $exemptionType->getResource()->save($exemptionType);

Snippet from customer_form.xml, changing fieldset name from 'customer' to 'my_tab' breaks the extension attributes.

<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<fieldset name="customer">
    <field name="my_exemption_type" formElement="select">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="label" xsi:type="string" translate="true">Exemption Type</item>
                <item name="source" xsi:type="string">customer</item>
            </item>
        </argument>
        <settings>
            <visible>true</visible>
        </settings>
    </field>
</fieldset>

Any help with either moving attributes to different tabs, creating a new admin form, or a different approach I haven't considered are appreciated!

Was it helpful?

Solution

I know this post is old, but decided to add my findings of a working solution, after spending hours looking at this.

First off, I had to try and understand the concepts of Magento's UI components and find a simple way to achieve this, without writing additional classes and data models. Here is some good reading material if anyone is interested:

https://devdocs.magento.com/guides/v2.4/ui_comp_guide/concepts/ui_comp_data_source.html

The solution:

  1. Programatically install the customer attributes. I wont go into detail for this since everyone has their on way of installing customer attributes and the install / update script in the original question should be sufficient. The only thing you would need to change is 'visible' => false, so that the attribute does not show under the default "Account Information" tab.

  2. Add "view/adminhtml/ui_component/customer_form.xml" to your module with the following (obviously update the fieldset names and field name to whatever you require):

    <form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="rfm">
        <settings>
            <collapsible>false</collapsible>
            <label translate="true">RFM Information</label>
            <componentType>fieldset</componentType>
            <dataScope>customer</dataScope>
        </settings>
        <fieldset name="rfm_group">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string" translate="true">General Information</item>
                    <item name="dataScope" xsi:type="string">customer</item>
                    <item name="sortOrder" xsi:type="number">1</item>
                    <item name="collapsible" xsi:type="boolean">true</item>
                    <item name="opened" xsi:type="boolean">true</item>
                </item>
            </argument>
            <field name="rfm_recency" formElement="input">
                <argument name="data" xsi:type="array">
                    <item name="config" xsi:type="array">
                        <item name="source" xsi:type="string">customer</item>
                    </item>
                </argument>
                <settings>
                    <label translate="true">Recency</label>
                    <dataType>text</dataType>
                    <visible>true</visible>
                    <imports>
                        <link name="value">${ $.provider }:data.customer.rfm_recency</link>
                    </imports>
                    <exports>
                        <link name="value">${ $.provider }:data.customer.rfm_recency</link>
                    </exports>
                </settings>
            </field>
        </fieldset>
    </fieldset>
    

You will notice i have a nested fieldset with a single input field, where the input field name would be composed like rfm[rfm_group][rfm_recency]. In order to compose the field name like customer[rfm_recency], we need to set a <dataScope> in each fieldset nodes and field nodes. You will see how I do this in my example above.

Next you will notice I have included imports and exports nodes under the field node.

  • The imports node (read) is telling the Magento UI which data value I want to link to my attribute value.
  • The exports node (write) is telling the Magento UI where I want to save my attribute value to.

Once you have implemented the customer_form.xml, clear the caches and reload your customer edit page. You should see something similar to this:

enter image description here

You will just need to make sure that the attribute is not visible in the "Account information" tab and the value actually saves as expected.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top