1

I used the Magento 2 plugin in PhpStorm to create an entity with grid and form. It seems to work great until I renamed the fieldset name to “foo” and added tabs.

I already looked up many related posts/questions and did some digging in de vendor folder. But I can't seem to find it, the data simply won't fill the input fields unless the fieldset name is general. here is a code snippet of my form: app/code/Vendor/SalesPromotion/view/adminhtml/ui_component/sales_promotion_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">
    <argument name="data" xsi:type="array">
        <item name="js_config" xsi:type="array">
            <item name="provider" xsi:type="string">sales_promotion_form.sales_promotion_form_data_source</item>
            <item name="deps" xsi:type="string">sales_promotion_form.sales_promotion_form_data_source</item>
        </item>
        <item name="config" xsi:type="array">
            <item name="dataScope" xsi:type="string">data</item>
            <item name="namespace" xsi:type="string">sales_promotion_form_data_source</item>
        </item>
        <item name="label" xsi:type="string" translate="true">Sales Promotion Form</item>
    </argument>
    <settings>
        <layout>
            <navContainerName>left</navContainerName>
            <type>tabs</type>
        </layout>
        <buttons>
            <button name="save" class="Vendor\SalesPromotion\Block\Form\SalesPromotion\Save"/>
            <button name="back" class="Vendor\SalesPromotion\Block\Form\SalesPromotion\Back"/>
            <button name="delete" class="Vendor\SalesPromotion\Block\Form\SalesPromotion\Delete"/>
        </buttons>
    </settings>
    <dataSource name="sales_promotion_form_data_source" component="Magento_Ui/js/form/provider">
        <settings>
            <submitUrl path="sales_promotion/salespromotion/save"/>
        </settings>
        <dataProvider class="Vendor\SalesPromotion\Ui\DataProvider\SalesPromotionDataProvider" name="sales_promotion_form_data_source">
            <settings>
                <requestFieldName>sales_promotion_id</requestFieldName>
                <primaryFieldName>sales_promotion_id</primaryFieldName>
            </settings>
        </dataProvider>
    </dataSource>
    <fieldset name="foo" sortOrder="10">
        <settings>
            <label translate="true">General</label>
            <dataScope/>
        </settings>
        <field name="sales_promotion_id" sortOrder="0" formElement="hidden">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">sales_promotion_id</item>
                </item>
            </argument>
            <settings>
                <dataType>text</dataType>
                <label translate="true">Entity ID</label>
                <dataScope>sales_promotion_id</dataScope>
            </settings>
        </field>
        <field name="name" sortOrder="00" formElement="input">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">name</item>
                </item>
            </argument>
            <settings>
                <dataType>string</dataType>
                <label translate="true">Name</label>
                <dataScope>name</dataScope>
            </settings>
        </field>
    </fieldset>
    <fieldset name="bar" sortOrder="20">
        <settings>
            <label translate="true">Conditions</label>
            <dataScope/>
        </settings>
        <field name="min_cart_total" sortOrder="80" formElement="input">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">min_cart_total</item>
                </item>
            </argument>
            <settings>
                <dataType>float</dataType>
                <label translate="true">Min Cart Total</label>
                <dataScope>min_cart_total</dataScope>
            </settings>
        </field>
    </fieldset>
    <fieldset name="howdy" sortOrder="30">
        <settings>
            <label translate="true">Email</label>
            <dataScope/>
        </settings>
        <field name="email_template" sortOrder="110" formElement="input">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">email_template</item>
                </item>
            </argument>
            <settings>
                <dataType>string</dataType>
                <label translate="true">Email Template</label>
                <dataScope>email_template</dataScope>
            </settings>
        </field>
    </fieldset>
</form>

2 Answers 2

2

Addition to the correct answer from @ThatOneGuyThatDontGetIt :


Another way to lead all fields to correct data source is to set dataScope of the form as data.general globally, as in example:

<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <settings>
        <dataScope>data.general</dataScope>

After that, you no longer need to specify the correct scope on each filed, all data will be automatically linked with ${ $.provider }:data.general

1

After some more debugging, and finding this post: https://magento.stackexchange.com/a/311982/73528 . I came to the idea to look around in the vendor/magento/module-ui/Component/Form.php file here we see the following:

public function getDataSourceData()
{
    $dataSource = [];
    $id = $this->getContext()->getRequestParam($this->getContext()->getDataProvider()->getRequestFieldName(), null);
    $idFieldName = $this->getContext()->getDataProvider()->getPrimaryFieldName();
    $filter = $this->filterBuilder->setField($idFieldName)
        ->setValue($id)
        ->create();
    $this->getContext()->getDataProvider()
        ->addFilter($filter);

    $data = $this->getContext()->getDataProvider()->getData();

    if (isset($data[$id])) {
        $dataSource = [
            'data' => $data[$id]
        ];
    } elseif (isset($data['items'])) {
        foreach ($data['items'] as $item) {
            if ($item[$idFieldName] == $id) {
                $dataSource = ['data' => ['general' => $item]];
            }
        }
    }
    return $dataSource;
}

so this means if it can't find the array key similar to the id of the entity it will dump all data into the general field. And it does seem to ignore the in the fieldsets. So as a solution I added the id in my "loadedData" in my dataprovider:

    /**
     * Get data.
     *
     * @return array
     */
    public function getData(): array
    {
        if ($this->loadedData) {
            return $this->loadedData;
        }

        $this->loadedData = parent::getData();
        $itemsById = [];

        foreach ($this->loadedData['items'] as $item) {
            $itemsById[(int)$item[SalesPromotionInterface::SALES_PROMOTION_ID]] = $item;
        }

        if ($id = $this->request->getParam(SalesPromotionInterface::SALES_PROMOTION_ID)) {
            $this->loadedData['entity'] = $itemsById[(int)$id];
            $this->loadedData[$id] = $itemsById[(int)$id]; /// this line was added
        }

        return $this->loadedData;
    }

But! That's not all we also have to add the datascope to data in our ui_component form as following:

    <fieldset name="howdy" sortOrder="30">
        <settings>
            <label translate="true">Email</label>
            <dataScope>data</dataScope>
        </settings>

and now finally we see the data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.