5

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?

4
  • If you want to add column you have to add column using XML and also you need to add that in datasource. Jul 10, 2017 at 4:49
  • @idham-choudry , did you find any solution of the problem?
    – Vishal
    Oct 16, 2018 at 9:17
  • 1
    //Useful /vendor/magento/module-catalog/Ui/Component/Listing/Columns.php /vendor/magento/module-catalog/view/adminhtml/ui_component/product_listing.xml
    – Vishal
    Oct 16, 2018 at 14:57
  • did you find any solution for the problem? –@Vishal Oct 15, 2020 at 9:17

2 Answers 2

2
+50

I have a solution that consists in taking over both columns and dataprovider for sales grid.

<?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">
    <dataSource name="sales_order_grid_data_source">
        <dataProvider class="Mbs\SalesGrid\Ui\Component\Listing\DataProvider" name="sales_order_grid_data_source" />
    </dataSource>
    <columns name="sales_order_columns" class="Mbs\SalesGrid\Ui\Component\Listing\Columns" />
</listing>

data provider below:

  class DataProvider extends \Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider
    {
        public function __construct(
            $name,
            $primaryFieldName,
            $requestFieldName,
            ReportingInterface $reporting,
            SearchCriteriaBuilder $searchCriteriaBuilder,
            RequestInterface $request,
            FilterBuilder $filterBuilder,
            array $meta = [],
            array $data = []
        ) {
            parent::__construct($name, $primaryFieldName, $requestFieldName, $reporting, $searchCriteriaBuilder, $request, $filterBuilder, $meta, $data);
        }
    
        public function getData()
        {
            $data = parent::getData();
    
            foreach ($data['items'] as &$item) {
                $item['sales_day_created'] = $this->extraDayFromDate($item['created_at']);
                $item['sales_time_created'] = $this->extraTimeFromDate($item['created_at']);
            }
    
            return $data;
        }
}


**columns below:**

 class Columns extends \Magento\Ui\Component\Listing\Columns
    {
        /**
         * @var CustomColumnCreator
         */
        private $columnCreator;
    
        public function __construct(
            ContextInterface $context,
            CustomColumnCreator $columnCreator,
            array $components = [],
            array $data = []
        ) {
            parent::__construct($context, $components, $data);
            $this->columnCreator = $columnCreator;
        }
    
        public function prepare()
        {
            if (isset($this->components['created_at'])) {
                $billingNameColumn = $this->components['billing_name'];
    
                $column = $this->columnCreator->addColumnFromExistingColumn(
                    $billingNameColumn,
                    'sales_day_created',
                    'Sales Day',
                    11
                );
                $this->addComponent('sales_day_created', $column);
    
                $column = $this->columnCreator->addColumnFromExistingColumn(
                    $billingNameColumn,
                    'sales_time_created',
                    'Sales Time',
                    11
                );
                $this->addComponent('sales_time_created', $column);
            }
    
            parent::prepare();
        }

I did not put all the details as it is pretty much about parsing and I can add the full module if you need.

UPDATE: the customColumnCreator is responsible to create a column in the grid dynamically. It takes an existing column and does use its configuration to generate the new column. This is a convenient way to clone a column when we are happy about its basic configuration.

full code: https://bitbucket.org/magstaging/salesgrid/src/master/

20
  • Not sure I understand, is it a question? Oct 16, 2020 at 6:49
  • In Columns.php i don't understand what is CustomColumnCreator can you please explain @Herve Tribouilloy Oct 16, 2020 at 7:07
  • I have updated my answer with explanations Oct 16, 2020 at 7:21
  • ya I have a collection if I just use the collection instead of CustomColumnCreator if I m wright Oct 16, 2020 at 7:21
  • I suggest paste all your code or module and then I can comment but the collection and the column creator are 2 different things Oct 16, 2020 at 7:23
1

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.

1
  • No, I want for the custom column not for custom data but your answer will help me in future Oct 16, 2020 at 6:28

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.