11

I have a grid UI component which is inside fieldset of some edited form. I need to pass an entity_id from the edit form to grid where an I can filter collection of some items by some value, and grid will show appropriate result. I created the grid component using an insertListing component.

<insertListing name="slide_grid">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="autoRender" xsi:type="boolean">true</item>
                <item name="source" xsi:type="string">slide</item>
                <item name="loading" xsi:type="boolean">true</item>
                <item name="dataScope" xsi:type="string">some_slider_slide_listing</item>
                <item name="externalProvider" xsi:type="string">${ $.ns }.some_slider_slide_listing_data_source</item>
                <item name="ns" xsi:type="string">some_slider_slide_listing</item>
                <item name="externalData" xsi:type="string">id</item>
                <item name="imports" xsi:type="array">
                    <item name="slider_id" xsi:type="string">${ $.provider }:data.entity_id</item>
                </item>
                <item name="exports" xsi:type="array">
                    <item name="slider_id" xsi:type="string">${ $.externalProvider }:params.slider_id</item>
                </item>
            </item>
        </argument>
    </insertListing>

For transfering data to external dataProvider I am using

<item name="exports" xsi:type="array">
                <item name="slider_id" xsi:type="string">${ $.externalProvider }:params.slider_id</item>
            </item>

Inside my external data provider i trying to get the data through request.

$this->request->getParam('slider_id');

But nothing. On frontend, i found that Magento sending ajax request with my parameter but I can't catch this in my DataProvider and filter the collection.

3
  • The approach I got from Magento 2 core code (For example in products CustomOptions form Modifier). But for some reason it is not working for me. – Mistery Aug 19 '17 at 11:12
  • Did you get any solution of the issue... I am facing same issue, please help if you have solved... – Ashish Raj Sep 27 '18 at 5:49
  • I made a same insertListing tag like you but the ajax request didn't have my parameter in the exports tag .... Did you find the solution? – thanhdv2811 Jan 13 '19 at 16:55
4

For add insert listing by param of parent ui-component we can use below code.

Here externalProvider tag is for add source provider of the listing which we are inserting.

Here imports tag is used for import param of the current form data source

Here exports tag is used for export the current form data params to the listing which going to be insert.

<insertListing name="slide_grid">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="autoRender" xsi:type="boolean">true</item>
            <item name="ns" xsi:type="string">slide_grid</item><-- data source of the inserted listing -->
            <item name="externalProvider" xsi:type="string">colors_one_listing.colors_one_listing_data_source</item><!-- your insert listing data provider source -->
            <item name="imports" xsi:type="array">
                <item name="spd_id" xsi:type="string">${ $.provider }:data.slider_id</item>
            </item>
            <item name="exports" xsi:type="array">
                <item name="slider_id" xsi:type="string">${ $.externalProvider }:params.slider_id</item>
            </item>
        </item>
    </argument>
</insertListing>

Add join with relevant column to the current collection for make it use in two ways:

  1. Filter by grid dataSource > argument name > "dataProvider" > argument name > "data" > item name "config" > item name="filter_url_params" => item name > "slider_id".

For more detail check below code:

<dataSource name="..._listing_data_source">
    <argument name="dataProvider" xsi:type="configurableObject">
        <argument name="class" xsi:type="string">...\...\Ui\DataProvider\...\Grid\...DataProvider</argument>
        <argument name="name" xsi:type="string">..._listing_data_source</argument>
        <argument name="primaryFieldName" xsi:type="string">id</argument>
        <argument name="requestFieldName" xsi:type="string">slider_id</argument>
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
                <item name="update_url" xsi:type="url" path="mui/index/render"/>
                <item name="filter_url_params" xsi:type="array">
                    <item name="slider_id" xsi:type="string">*</item>
                </item>
                <item name="storageConfig" xsi:type="array">
                    <item name="indexField" xsi:type="string">id</item>
                </item>
            </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/grid/provider</item>
        </item>
    </argument>
</dataSource>
  1. Filter the data provider of inserted listing.

In the data provider add filter for this param:

$collection->addFieldToFilter('slider_id', $this->request->getParam('slider_id'));

I like to follow option 1.

1
  • dataProvider doesn't have the filter_url_params parameters in the definition. Please update your anwser. – Michelangelo Mar 3 '20 at 15:31
4

After reading and debugging the Magento 2 core files I have found a clean and simple solution about this issue. Passing data from a custom form to a custom grid using the UIComponent insertListing is really hard and not documented at all.

enter image description here

The InsertListing object has two parameters under the tag: exports and imports that I have used in my listing:

<fieldset name="relatedto" >
    <settings>
        <label>Related to</label>
        <componentType>fieldset</componentType>
    </settings>

    <insertListing name="threadrelated_listing">
        <settings>
            <dataLinks>
                <exports>false</exports>
                <imports>true</imports>
            </dataLinks>
            <externalProvider>mycompany_helpdesk_threadrelated_listing.mycompany_helpdesk_threadrelated_listing_data_source</externalProvider>
            <selectionsProvider>mycompany_helpdesk_threadrelated_listing.mycompany_helpdesk_threadrelated_listing.mycompany_helpdesk_threadrelated_columns.ids</selectionsProvider>
            <autoRender>true</autoRender>
            <dataScope>mycompany_helpdesk_threadrelated_listing</dataScope>
            <ns>mycompany_helpdesk_threadrelated_listing</ns>
            <exports>
                <link name="ticket_id">${ $.externalProvider }:params.ticket_id</link>
            </exports>
            <imports>
                <link name="ticket_id">${ $.provider }:data.ticket_id</link>
            </imports>
        </settings>
    </insertListing>
</fieldset>

and after hours to understand and find a solution on the web, I have not found any clue!

So I have read the Magento Core file and I have discovered that Magento meshups the way to create the nested listing grids in the project. Sometime it uses the old block insert method and few times the new UIComponent listing method.

I have found the customer address listing grid at the customer_address_listing.xml (/vendor/magento/module-customer/view/adminhtml/ui_component/customer_address_listing.xml) and it gets the parent_id variable defined in the customer_form.xml (/vendor/magento/module-customer/view/base/ui_component/customer_form.xml) but the question is:

How Magento pass the data from the form to the nested listing grid?

Magento pass the data by the QUERYSTRING PARAMETER!

If you read the DataProvider.php file you will be surprised because it gets the parent_id (customer) variable by the QUERYSTRING! Look at /vendor/magento/module-customer/Ui/Component/Listing/Address/DataProvider.php line 58:

/**
 * Add country key for default billing/shipping blocks on customer addresses tab
 *
 * @return array
 */
public function getData(): array
{
    $collection = $this->getCollection();
    $data['items'] = [];
    if ($this->request->getParam('parent_id')) {
        $collection->addFieldToFilter('parent_id', $this->request->getParam('parent_id'));
        $data = $collection->toArray();
    }
    foreach ($data['items'] as $key => $item) {
        if (isset($item['country_id']) && !isset($item['country'])) {
            $data['items'][$key]['country'] = $this->countryDirectory->loadByCode($item['country_id'])->getName();
        }
    }

    return $data;
}

but how do I set the parameter in the listinggrid URL? I have found the filterUrlParams parameter but there is an odd issue also here! Let take a look at this snipped of dataSource code:

<dataSource name="mycompany_helpdesk_threadrelated_listing_data_source" component="Magento_Ui/js/grid/provider">
    <settings>
        <filterUrlParams>
            <param name="ticket_id">*</param>
        </filterUrlParams>
        <storageConfig>
            <param name="indexField" xsi:type="string">threadrelated_id</param>
        </storageConfig>
        <updateUrl path="mui/index/render"/>
    </settings>
    <dataProvider class="mycompany\Helpdesk\Ui\DataProvider\Threadrelated\ThreadRelatedDataProvider" name="mycompany_helpdesk_threadrelated_listing_data_source">
        <settings>
            <requestFieldName>id</requestFieldName>
            <primaryFieldName>threadrelated_id</primaryFieldName>
        </settings>
    </dataProvider>
</dataSource>

I have set the ticket_id with a wildcard (*) that it means: get all the tickets! but if you do not set any ID in the filterUrlParams the insertListing URL has NOT ANY ticket_id SET! So why?!

The solution offered by @hashish-raj doesn't work for me.

These are all the post that I have read about this issue:

At the end I have found a temporary workaround using the core session and store the ticket_id parameter in the session. Then in the custom dataprovider I have check it and I have applied it to the collection:

/***
 * @return array
 */
public function getData()
{

    $collection = $this->getSearchResult();

    /** see: check Mycompany\Helpdesk\Controller\Adminhtml\Ticket\Edit **/
    if($this->coreSession->getTicketId()){
        $collection->addFieldToFilter('ticket_id', ['eq' => $this->coreSession->getTicketId()]);
    }

    return $this->searchResultToOutput($collection);

}

If you have a workaround or you have understood how Magento handles this relationship between the UIComponent, please share your knowledge!

I have opened a "bounty" here: https://magento.stackexchange.com/a/306537/2004

1
  • nice explanation. Love it :) – Amit Bera Oct 20 '20 at 10:12
0

this work for me!

// Vendor/Module/view/adminhtml/ui_component/customer_form.xml
...
<insertListing name="..._listing">
        <settings>
            <externalProvider>..._listing...._listing_data_source</externalProvider>
            <selectionsProvider>..._listing...._listing...._listing_columns.ids</selectionsProvider>
            <autoRender>true</autoRender>
            <dataScope>company_account_listing</dataScope>
            <ns>company_account_listing</ns>
            <imports>
                <link name="same">${ $.provider }:data.customer.website_id</link>
            </imports>
            <exports>
                <link name="same">${ $.externalProvider }:params.new_new</link>
            </exports>
        </settings>
    </insertListing>

// Vendor/Module/view/adminhtml/ui_component/...listing.xml
<dataSource name="..._listing_data_source" component="Magento_Ui/js/grid/provider">
    <settings>
        <storageConfig>
            <param name="indexField" xsi:type="string">entity_id</param>
        </storageConfig>
        <updateUrl path="mui/index/render"/>
    </settings>
    <aclResource>anonymous</aclResource>
    <dataProvider class="Vendor\Module\Ui\Component\DataProvider" name="..._listing_data_source">
        <settings>
            <requestFieldName>entity_id</requestFieldName>
            <primaryFieldName>entity_id</primaryFieldName>
        </settings>
    </dataProvider>
</dataSource>

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.