Magento 2 UI components allow to generate and display several lists and grid types. As well you can create your own component based on the already existing code, but that’s the topic for another article.
Now I want to describe how to extend sales order grid with an additional column.
Adding a new column to a grid is not so complex task as distinct from creation a column with filtering. Let’s take a look how to perform it in Magento 2.1, by adding a new column into the order grid.
Note. The code listed below in XML format is valid only for Magento 2.1 version or later. And we are not going to consider a code for elder versions in this article. If you still use Magento 1, we highly recommend that you migrate to Magento 2.
All of the directives are placed in the <module>/view/adminhtml/ui_component/ directory. Let’s create the “sales_order_grid.xml” file. The name of the file has to match with a parent component, which we want to extend.
So let’s add the code into the file as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd"> <columns> <column name="example_status" class="Module\Ui\Component\Columns\OrderGrid"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="label" xsi:type="string" translate="true">Status example</item> <item name="sortOrder" xsi:type="number">50</item> <item name="align" xsi:type="string">left</item> <item name="dataType" xsi:type="string">text</item> <item name="visible" xsi:type="boolean">true</item> <item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item> </item> </argument> </column> </columns> </listing> |
Let’s break down this code:
Partner With Us
Let's discuss how to grow your business. Get a Free Quote.In line
1 |
<column name="example_status" class="Module\Ui\Component\Columns\OrderGrid"> |
We add the column into order grid. Class Module\Ui\Component\Columns\OrderGrid should extend the Magento\Ui\Component\Listing\Columns\Column class.
We should override the prepareDataSource() method:
1 2 3 4 5 6 7 8 9 |
public function prepareDataSource(array $dataSource) { if (isset($dataSource['data']['items'])) { foreach ($dataSource['data']['items'] as &$item) { //put logic here } } return $dataSource; } |
Current grid row data is stored in the variable $item. The name of the column is available in the array element “name”:
1 |
$item[$this->getData('name')] = $value; |
Thus we can fill the row the data.
But let’s get back to the sales_order_grid.xml file. All what we can see in the argument line and below is related to the description of column.
1 |
<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item> |
The following line states that we can render any valid HTML code in the cell. Magento 2 supports a few pre-defined template renders out of the box, all of them are placed in the module-ui.
In the following example we didn’t specify the component, but additionally, we can specify the component of the column in argument tag as well. For example:
1 |
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item> |
Component defines which type of column will be used. For example, it could be date, column, actions, multiselect, select or thumbnail type. As well as templates, all of the components are placed in the module-ui. At this stage, we already have the column in order grid, and in case we don’t need the filtering by this column, we can finish. But if we do, that is becoming not so easy task.
Magento Webdesign
Take your online store to the next level with BelVG Magento Webdesign
Visit the pageThere are 2 ways of solving the problem:
- To add our column into sales_order and sales_order_grid tables and control CRUD operations for the sales_order table (sales_order_grid table is synchronized with sales_order table by cron).
- To write a new plugin for rapid column update.
In my view sales_order table update way leads to the overmuch data and compatibility reduction. That’s why I decided to perform it through the plugin filtering. At first, let’s add the filter into sales_order_grid.xml file. Then add the following code right after the close tag:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<listingToolbar name="listing_top"> <filters name="listing_filters"> <filterSelect name="example_status"> <argument name="optionsProvider" xsi:type="configurableObject"> <argument name="class" xsi:type="string">Modulei\Model\Config\Statuses</argument> </argument> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="provider" xsi:type="string">${ $.parentName }</item> <item name="dataScope" xsi:type="string">example_status</item> <item name="caption" xsi:type="string" translate="true">Select status</item> <item name="label" xsi:type="string" translate="true">Select status</item> <item name="component" xsi:type="string">Magento_Ui/js/form/element/ui-select</item> <item name="template" xsi:type="string">ui/grid/filters/elements/ui-select</item> </item> </argument> </filterSelect> </filters> </listingToolbar> |
So we are going to create dropdown filter, with multiselect.
In line:
1 |
<argument name="class" xsi:type="string">Modulei\Model\Config\Statuses</argument> |
We designate class, in which filter value will be defined. This class should carry out interface \Magento\Framework\Data\OptionSourceInterface.
The line
1 |
<item name="provider" xsi:type="string">${ $.parentName }</item> |
defines the provider we use. In this case, we are using the parental provider.
For each filter, we should designate collection, where data will be shown
Statement ${ $.parentName} referrers to the collection used by default. dataSource tag specifies the collection name. For example, for order sales grid it should be as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<dataSource name="sales_order_grid_data_source"> <argument name="dataProvider" xsi:type="configurableObject"> <argument name="class" xsi:type="string">Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider</argument> <argument name="name" xsi:type="string">sales_order_grid_data_source</argument> <argument name="primaryFieldName" xsi:type="string">entity_id</argument> <argument name="requestFieldName" xsi:type="string">id</argument> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="update_url" xsi:type="url" path="mui/index/render"/> <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item> </item> </argument> </argument> </dataSource> |
Magento 2 Migration
Take your online store to the next level with BelVG Magento 2 Migration
Visit the pageThe collection class for the order sales is sales_order_grid_data_source, which is defined in vendor/magento/module-sales/etc/di.xml:
1 2 3 4 |
<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory"> <arguments> <argument name="collections" xsi:type="array"> <item name="sales_order_grid_data_source" xsi:type="string">Magento\Sales\Model\ResourceModel\Order\Grid\Collection</item> |
So we use the collection as a source for filtering. And now, all that we have to do is to add a plugin, which could add our data into filtering results.
Let’s register a plugin in etc/di.xml
1 2 3 4 5 6 7 8 |
<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory"> <plugin name="sales_order_additional_columns" type="Module\Plugin\AdditionalFields\CollectionFactory" sortOrder="100" disabled="false" /> </type> |
And add method Module\Plugin\AdditionalFields\CollectionFactory::aroundGetReport()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public function aroundGetReport( \Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory $subject, \Closure $proceed, $requestName ) { $result = $proceed($requestName); if ($requestName == 'sales_order_grid_data_source') { if ($result instanceof Magento\Sales\Model\ResourceModel\Order\Grid\Collection) { //add code to join table, and mapping field to select } } return $result; } |
Filtering by the current field should be available after plugin installation.
The following lines
1 2 |
<item name="component" xsi:type="string">Magento_Ui/js/form/element/ui-select</item> <item name="template" xsi:type="string">ui/grid/filters/elements/ui-select</item> |
are needed for multiselect rendering, and if we remove them, parental filter type-select will be in use by default. The current filter helps to perform selecting by several filter values.
As a result, we have:
Magento 2 provides a very comfortable way of adding the column into order grid. But in case you need to add filtering by the current column, there are 2 ways.
The first is more simple — to add two columns into the sales_order and sales_order_grid tables. But this way has a few disadvantages.
And another one I’ve just covered in this article — adding filter through the plugins method. This method is quite more complex, but it has no disadvantages that we mentioned before.
UPD: Magento has changed some syntax of *.xml files for ui-components for 2.1.3 and newer versions. Here is a module with an example: https://github.com/Galillei/sample_add_columns_to_order_grid. It has been successfully tested on Magento 2.1.4 CE, and it should work on Magento 2.1.5 as well.
Need a quality Magento extension for great Administration functionalities? Visit out BelVG store!
Magento Custom Development
Take your online store to the next level with BelVG Magento Custom Development
Visit the page
I think you can. But you need use custom template for ui-component. For example i set to grid block of returned items from order: http://prntscr.com/jql1kw
Hello Artsem,
Excellent article regarding additional columns in order grid. I also would like to know, if we can add just products ordered in an order and its quantity as an additional column in magento2 order grid.
Thanks in Advance !
Hi Lakmal!
Magento often redesigns its UI-components. The same situation was when we were upgrading from 2.1.0 to 2.1.3. We haven’t still updated to 2.1.7 version, but I think that error occurs in *.xml files of UI component, so you should check *.xml files of your code.
Kindly,
Artsem
Hi @ARTSEM
The filter section disappear after loading in Magento 2.1.7, any idea why?
Thanks
Lakmal
Hello Artsem Miklashevich,
GOD BLESS YOU.
You made my day :-)
Hello Artsem Miklashevich, Please can you tell me how to add product image as a new column inside order view page?
Hi! Magento has changed some syntax of *.xml files for ui-components for 2.1.3 and newer versions. Here is a module with example: https://github.com/Galillei/sample_add_columns_to_order_grid . I’ve just successfully tested it on Magento 2.1.4 CE, and it should work on magento 2.1.5 as well.
Hi, can you please share the sample code? it not working for me (Magento 2.1.5)
Thanks
Ui\Component\Columns\OrderGrid does not exist
Hi,
Would be share the sample code please for this tutorial?
Would be kind help.
Thanks
Hi Artsem, Where can I find your sample code?
Thanks for the post. Its working rocks. Can we add category filter in product grid in magento2?
@Marsh you can check this article http://blog.belvg.com/how-to-manage-displaying-of-sales-order-grid-columns-in-magento.html
Thanks for the great post. Would it is possible to do this in Magento 1?