Magento – Add custom dynamic column in sales order grid Magento 2

dynamic rowsgridmagento2order-grid

This solution shows how to add a custom column to the sales order grid, but to add a custom column you need to add the column via XML, the problem is i need to read data collection to get available column data and add it as a custom column in sales order grid, in conclusion, I want to add multiple columns which will be generated dynamically from database collection data, is there any way to do this?

Best Answer

Make new sales_order_grid.xml file in app/code/YourVendor/YourModule/view/adminhtml/ui_component/ and try to do there something like this:

<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <columns name="sales_order_columns">
        <column name="your_column" class="YourVendor\YourModule\Ui\Component\YourColumn">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="sortOrder" xsi:type="number">10</item>
                </item>
            </argument>
        </column>
    </columns>
</listing>

That class property inside column tag allows you to write your very own renderer that will take care of the custom column. You can do it simply like that:

<?php

declare(strict_types=1);

namespace YourVendor\YourModule\Ui\Component;

use Magento\Ui\Component\Listing\Columns\Column;

class YourColumn extends Column
{
    /**
     * @param array $dataSource
     *
     * @return array
     */
    public function prepareDataSource(array $dataSource): array
    {
        parent::prepareDataSource($dataSource);

        if (!isset($dataSource['data']['items'])) {
            return $dataSource;
        }

/* 
In this method the `$dataSource` array contains informations from order grid. 
To access your dynamic field name you don't need to refer to the xml file, 
you can just simply use $this->getData('name') to obtain the name of your renderer column.
*/
        foreach ($dataSource['data']['items'] as & $item) {
            //for example:
            $item[$this->getData('name')] = 'HelloWorld'; //will display the "HelloWorld" string at every row of your custom column

            $item[$this->getData('name')] = $item['increment_id'];//will display increment_id value at every row of your custom column

            //you can also perform simple operations, for example:
            if($item['increment_id'] === '123456789'){
                $item[$this->getData('name')] = 'Increment id is fake';
            }
        }

        return $dataSource;
    }
}

Let me know if it's what you've wanted.

Related Topic