Magento 2 How to Add a New Column to Orders Grid
After lots of digging into Magento's core code, I found a solution to my question. Instead of adding a column to the grid via the database, I created a UI component sales_order_grid.xml
under [COMPANY]/[MODULE]/view/adminhtml/ui_component/sales_order_grid.xml
<?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="export_status" class="[COMPANY]\[MODULE]\Ui\Component\Listing\Column\Status">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="visible" xsi:type="boolean">true</item>
<item name="label" xsi:type="string" translate="true">XML Exported</item>
</item>
</argument>
</column>
</columns>
</listing>
Then created the UI class under [COMPANY]/[MODULE]/Ui/Component/Listing/Column/Status.php
namespace [COMPANY]\[MODULE]\Ui\Component\Listing\Column;
use \Magento\Sales\Api\OrderRepositoryInterface;
use \Magento\Framework\View\Element\UiComponent\ContextInterface;
use \Magento\Framework\View\Element\UiComponentFactory;
use \Magento\Ui\Component\Listing\Columns\Column;
use \Magento\Framework\Api\SearchCriteriaBuilder;
class Status extends Column
{
protected $_orderRepository;
protected $_searchCriteria;
public function __construct(ContextInterface $context, UiComponentFactory $uiComponentFactory, OrderRepositoryInterface $orderRepository, SearchCriteriaBuilder $criteria, array $components = [], array $data = [])
{
$this->_orderRepository = $orderRepository;
$this->_searchCriteria = $criteria;
parent::__construct($context, $uiComponentFactory, $components, $data);
}
public function prepareDataSource(array $dataSource)
{
if (isset($dataSource['data']['items'])) {
foreach ($dataSource['data']['items'] as & $item) {
$order = $this->_orderRepository->get($item["entity_id"]);
$status = $order->getData("export_status");
switch ($status) {
case "0":
$export_status = "No";
break;
case "1";
$export_status = "Yes";
break;
default:
$export_status = "Failed";
break;
}
// $this->getData('name') returns the name of the column so in this case it would return export_status
$item[$this->getData('name')] = $export_status;
}
}
return $dataSource;
}
}
My solution may be a bit more efficient since it follows the native way of adding a column to the grid, and you won't have to load every order displayed on the page to obtain the column data (utilizing the sales_order_grid table instead). The above is a great example of how to create a customized renderer though.
vendor/[vendor]/[package]/view/adminhtml/ui_component/sales_order_grid.xml
<!-- Add the column "my_column" (My Column) to the sales order grid. -->
<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="my_column">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="filter" xsi:type="string">text</item>
<item name="label" xsi:type="string" translate="true">My Column</item>
</item>
</argument>
</column>
</columns>
Please note that you must enable the column using the drop-down widget above the order grid before it appears.
vendor/[vendor]/[package]/etc/di.xml
<!-- Sync the column "my_column" between the sales_order and sales_order_grid tables -->
<virtualType name="Magento\Sales\Model\ResourceModel\Order\Grid" type="Magento\Sales\Model\ResourceModel\Grid">
<arguments>
<argument name="columns">
<item name="my_column" xsi:type="string">sales_order.my_column</item>
</argument>
</arguments>
</virtualType>
Sample setup code to add a column to sales_order_grid table (use this in your install/upgrade script). The same code works for the sales_order table by the way.
$setup->getConnection()->addColumn(
$setup->getTable('sales_order_grid'),
'my_column',
[
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
'length' => 255,
'nullable' => true,
'comment' => 'My Column'
]
);
Hope it helps! :-)