4

I am working on magento 2.1 backend module. Basically backend part is a form that contain tabs. Here i have some standard inputs but also some dynamic rows etc. Everything is working fine except the last tab. Last tab is a MODAL that allow us to choose products that will not be available for the entity that we are editing/creating.

Basically idea of working is exactly same as on product edit form for related products, so: we have a button "Add related products", modal render with grid of products then we can select them and after click "Add selected products" we have them rendered in dynamic grid rows.

I was able to reproduce some part of this logic on my custom form:

  • custom tab with button "Add unavailable products"
  • after click modal render
  • inside modal I have a product list
  • when selecting product and clicking "Add selected products" modal disappear
  • when opening modal again the list is filtered (does not contain previously selected elements)
  • DYNAMIC GRID is not populated :(

I do not know where is the problem with dynamic grid. There are no errors in the console, no error logs, etc. Does anyone worked with those components or maybe have a idea what to do to make it works?

I saw some referrences into this doc: http://devdocs.magento.com/guides/v2.1/ui-components/ui_dynamic_rows.html but it is not working.

This is how the tab looks like: Edit form tab with modal

Some implementation details:

Main form is declared on adminhtml/ui_component/my_component_form.xml and looks like this:

<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">my_component_form.my_component_form_data_source</item>
        <item name="deps" xsi:type="string">my_component_form.my_component_form_data_source</item>
        <item name="namespace" xsi:type="string">my_component_form</item>
    </item>
    <item name="label" xsi:type="string" translate="true">Agency Information</item>
    <item name="layout" xsi:type="array">
        <item name="type" xsi:type="string">tabs</item>
        <item name="navContainerName" xsi:type="string">left</item>
    </item>
    <item name="buttons" xsi:type="array">
        <item name="back" xsi:type="string">MyModule\Agency\Block\Adminhtml\Agency\Edit\BackButton</item>
        <item name="delete" xsi:type="string">MyModule\Agency\Block\Adminhtml\Agency\Edit\DeleteButton</item>
        <item name="reset" xsi:type="string">MyModule\Agency\Block\Adminhtml\Agency\Edit\ResetButton</item>
        <item name="save" xsi:type="string">MyModule\Agency\Block\Adminhtml\Agency\Edit\SaveButton</item>
        <item name="save_and_continue" xsi:type="string">MyModule\Agency\Block\Adminhtml\Agency\Edit\SaveAndContinueButton</item>
    </item>
    <item name="reverseMetadataMerge" xsi:type="boolean">true</item>
</argument>
<dataSource name="my_component_form_data_source">
    <argument name="dataProvider" xsi:type="configurableObject">
        <argument name="class" xsi:type="string">MyModule\Agency\Ui\Component\Edit\Form</argument>
        <argument name="name" xsi:type="string">my_component_form_data_source</argument>
        <argument name="primaryFieldName" xsi:type="string">agency_id</argument>
        <argument name="requestFieldName" xsi:type="string">agency_id</argument>
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="submit_url" xsi:type="url" path="my_component/agency/save"/>
            </item>
        </argument>
    </argument>
    <argument name="data" xsi:type="array">
        <item name="js_config" xsi:type="array">
            <item name="component" xsi:type="string">Magento_Ui/js/form/provider</item>
        </item>
    </argument>
</dataSource>

Last tab is added with Modifier class (like Related product), and my adminhtml/di.xml file looks like:

    <virtualType name="MyModule\Agency\Ui\Component\Edit\Modifier\Pool" type="Magento\Ui\DataProvider\Modifier\Pool">
    <arguments>
        <argument name="modifiers" xsi:type="array">
            <item name="availability" xsi:type="array">
                <item name="class" xsi:type="string">MyModule\Agency\Ui\Component\Edit\Modifier\UnavailableProducts</item>
                <item name="sortOrder" xsi:type="number">200</item>
            </item>
        </argument>
    </arguments>
</virtualType>
<type name="MyModule\Agency\Ui\Component\Edit\Form">
    <arguments>
        <argument name="pool" xsi:type="object">MyModule\Agency\Ui\Component\Edit\Modifier\Pool</argument>
    </arguments>
</type>
<type name="MyModule\Agency\Ui\Component\Edit\Modifier\UnavailableProducts">
    <arguments>
        <argument name="scopeName" xsi:type="string">my_component_form.areas</argument>
    </arguments>
</type>

My getMeta method on DataProvider class (Form) is:

    public function getMeta()
{
    $meta = parent::getMeta();

    /** @var ModifierInterface $modifier */
    foreach ($this->pool->getModifiersInstances() as $modifier) {
        $meta = $modifier->modifyMeta($meta);
    }

    return $meta;
}

And last part my modifier class extends Related products class, and field construction looks like:

 class UnavailableProducts extends Related
{
...
...
...
  /**
     * {@inheritdoc}
     */
    protected function getButtonSet(Phrase $content, Phrase $buttonTitle, $scope)
    {
        $config = parent::getButtonSet($content, $buttonTitle, $scope);
        $modalTarget = $this->scopeName . '.' . 'unavailable' . '.' . $scope . '.modal';

        // We need to update some button config in order to make sure that the modal box is linked to the proper button
        $config['children']['button_' . $scope]['arguments']['data']['config']['actions'][0]['targetName'] = $modalTarget;
        $config['children']['button_' . $scope]['arguments']['data']['config']['actions'][1]['targetName'] = $modalTarget . '.' . $scope . '_product_listing';

        return $config;
    }


    public function modifyMeta(array $meta)
    {
        $meta = array_replace_recursive(
            $meta,
            [
                // Let's add a new fieldset group
                static::EASYCORE_AGENCY => [
                    'children' => [
                        'button_set' => $this->getButtonSet(
                            __('Products that are present here are not available for this agency'),
                            __('Add Unavailable Products'),
                            $this->scopePrefix . 'unavailable'
                        ),
                        'modal' => $this->getGenericModal(
                            __('Add Unavailable Products'),
                            $this->scopePrefix . 'unavailable'
                        ),
                        'unavailable' => $this->getGrid('unavailable')
                    ],
                    'arguments' => [
                        'data' => [
                            'config' => [
                                'label' => __('Unavailable products'),
                                'collapsible' => false,
                                'componentType' => Fieldset::NAME,
                                'dataScope' => static::DATA_SCOPE,
                                'sortOrder' => 200
                            ],
                        ],

                    ],
                ],
            ]
        );

        return $meta;
    }

If we take a look inside Related class we will see that on grid config there is value like:

'links' => [
     'insertData' => '${ $.provider }:${ $.dataProvider }'
],

I suspect that the problem is somewhere on grid or dynamic row configuration... But I am unable to find it on my own :/ Any help would be great.

1 Answer 1

0

Looks like dynamicRows dataScope & dataProvider is wrong. I faced same problem. After changing dataScope & dataProvider grid is populated.

<dynamicRows name="orders">
<argument name="data" xsi:type="array">
    <item name="config" xsi:type="array">
        <item name="dataScope" xsi:type="string">data.orders_tab.links</item>
        <item name="dataProvider" xsi:type="string">data.orders_tab.my_module_sales_order_listing</item>
    </item>
</argument>
<container name="record"/>

Before:

<item name="dataScope" xsi:type="string">data.links</item>

After:

<item name="dataScope" xsi:type="string">data.orders_tab.links</item>

orders_tab is name of tab where are dynamicRows & insertListing placed.

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.