Skip to content
intermediate Phase 50 · Order Operations

Order Grids

Admin order grid, custom columns, filters, mass actions, and grid data providers

45m
0 problems
Topic Progress 0%

Order Grid Configuration

Grid UI Component

<!-- app/code/Vendor/Order/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">
    <settings>
        <spinner>listingColumns</spinner>
    </settings>
    <dataSource name="order_listing_data_source">
        <argument name="data" xsi:type="array">
            <item name="js_config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/data/provider</item>
            </item>
        </argument>
        <dataProvider class="Magento\Sales\Model\DataProvider" name="order_listing_data_source"/>
    </dataSource>
    <listingColumns name="listing_columns">
        <column name="increment_id" class="Magento\Ui\Component\Listing\Columns\Column">
            <settings>
                <filter>text</filter>
                <dataType>text</dataType>
                <label translate="true">Order #</label>
                <bodyTmpl>ui/grid/cells/html</bodyTmpl>
            </settings>
        </column>
        <column name="created_at" class="Magento\Ui\Component\Listing\Columns\Date">
            <settings>
                <filter>dateRange</filter>
                <dataType>date</dataType>
                <label translate="true">Purchase Date</label>
            </settings>
        </column>
        <column name="status" class="Magento\Ui\Component\Listing\Columns\Column">
            <settings>
                <filter>select</filter>
                <dataType>select</dataType>
                <label translate="true">Status</label>
            </settings>
        </column>
    </listingColumns>
</listing>

Grid Data Provider

namespace Vendor\Order\Ui\DataProvider;

class OrderDataProvider extends \Magento\Ui\Model\DataProvider
{
    public function __construct(
        string $name,
        string $primaryFieldName,
        string $requestFieldName,
        \Magento\Sales\Model\ResourceModel\Order\Grid\Collection $collection,
        array $meta = [],
        array $data = []
    ) {
        parent::__construct($name, $primaryFieldName, $requestFieldName, $collection, $meta, $data);
    }

    public function getData(): array
    {
        $items = $this->getCollection()->getItems();

        $result = [];
        foreach ($items as $item) {
            $result[$item->getId()] = $item->getData();
        }

        return [
            'totalRecords' => $this->getCollection()->getSize(),
            'items' => $result,
        ];
    }
}

Custom Columns

Adding Custom Columns

<!-- Add column to existing grid -->
<listingColumns>
    <column name="custom_field" class="Vendor\Order\Ui\Component\Column\Custom">
        <settings>
            <filter>text</filter>
            <dataType>text</dataType>
            <label translate="true">Custom Field</label>
            <sortOrder>50</sortOrder>
        </settings>
    </column>
</listingColumns>

Custom Column Class

namespace Vendor\Order\Ui\Component\Column;

use Magento\Ui\Component\Listing\Columns\Column;
use Magento\Framework\View\Element\UiComponent\ContextInterface;

class Custom extends Column
{
    public function prepareDataSource(array $dataSource): array
    {
        if (!isset($dataSource['data']['items'])) {
            return $dataSource;
        }

        foreach ($dataSource['data']['items'] as &$item) {
            $item['custom_field'] = $this->formatCustomValue(
                $item['custom_field']
            );
        }

        return $dataSource;
    }

    private function formatCustomValue($value): string
    {
        return strtoupper($value);
    }
}

Column with Custom Renderer

// Custom column renderer
define([
    'Magento_Ui/js/grid/columns/column',
    'text'
], function (Column, text) {
    'use strict';

    return Column.extend({
        defaults: {
            bodyTmpl: 'ui/grid/cells/html',
            component: 'Vendor_Order/js/column/custom'
        },

        getLabel: function (row) {
            return '<span class="custom-badge">' + row.custom_field + '</span>';
        }
    });
});

Grid Filters

Filter Types

<!-- Different filter types -->
<column name="status">
    <settings>
        <!-- Text filter -->
        <filter>text</filter>

        <!-- Select filter -->
        <filter>select</filter>

        <!-- Date range filter -->
        <filter>dateRange</filter>

        <!-- Numeric filter -->
        <filter>number</filter>

        <!-- Boolean filter -->
        <filter>boolean</filter>

        <options>
            <option name="processing" xsi:type="array">
                <item name="value" xsi:type="string">processing</item>
                <item name="label" xsi:type="string">Processing</item>
            </option>
            <option name="complete" xsi:type="array">
                <item name="value" xsi:type="string">complete</item>
                <item name="label" xsi:type="string">Complete</item>
            </option>
        </options>
    </settings>
</column>

Custom Filter

namespace Vendor\Order\Ui\Component\Filter;

class CustomFilter extends \Magento\Ui\Component\Listing\Columns\Column\Filter
{
    public function getFilterData(): array
    {
        $value = $this->request->getParam($this->getData('name'));

        if ($value) {
            return [
                'field' => $this->getData('dataScope'),
                'value' => ['like' => '%' . $value . '%'],
                'condition_type' => 'like'
            ];
        }

        return [];
    }
}

Mass Actions

Mass Action Configuration

<!-- Mass actions for order grid -->
<massaction name="listing_massaction">
    <action name="delete">
        <settings>
            <url path="sales/order/massDelete"/>
            <confirm>
                <message translate="true">Are you sure you want to delete selected orders?</message>
                <title translate="true">Delete Orders</title>
            </confirm>
        </settings>
    </action>
    <action name="status">
        <settings>
            <url path="sales/order/massStatus"/>
            <confirm>
                <message translate="true">Are you sure you want to change status?</message>
                <title translate="true">Change Status</title>
            </confirm>
        </settings>
        <argument name="data" xsi:type="array">
            <item name="options" xsi:type="array">
                <item name="processing" xsi:type="array">
                    <item name="value" xsi:type="string">processing</item>
                    <item name="label" xsi:type="string">Processing</item>
                </item>
                <item name="complete" xsi:type="array">
                    <item name="value" xsi:type="string">complete</item>
                    <item name="label" xsi:type="string">Complete</item>
                </item>
            </item>
        </argument>
    </action>
</massaction>

Custom Mass Action Controller

namespace Vendor\Order\Controller\Adminhtml\Order\Mass;

class MassCustom extends \Magento\Backend\App\Action
{
    public function execute()
    {
        $selected = $this->getRequest()->getParam('selected');

        if (!empty($selected)) {
            foreach ($selected as $orderId) {
                $order = $this->orderRepository->get($orderId);
                $order->setStatus('custom_status');
                $this->orderRepository->save($order);
            }

            $this->messageManager->addSuccessMessage(
                __('%1 orders updated successfully.', count($selected))
            );
        }

        return $this->_redirect('sales/order/index');
    }
}

Quiz

1. What is a grid data provider?

Question 1 options

2. How do you add a custom column to the order grid?

Question 2 options

3. What does mass action allow?

Question 3 options

Flashcards

Question

Grid root element?

Answer

<listing> in UI component XML

Question

Grid data source?

Answer

dataSource element with PHP DataProvider class

Question

Mass action purpose?

Answer

Bulk operations on selected grid items

Question

Column filter types?

Answer

text, select, dateRange, number, boolean

Revision Notes

Key Takeaways

  • 1. Order grids use UI component XML with <listing> root element
  • 2. Grid data providers supply data via getData() method
  • 3. Custom columns are added via <column> elements with PHP classes
  • 4. Mass actions enable bulk operations on selected orders
  • 5. Filters support multiple types: text, select, date, number

Interview Tips

  • Explain the grid component architecture: XML → JS → PHP data
  • Describe how to add a custom column with data transformation
  • Discuss mass action implementation and controller handling

Cheat Sheet

Grid Components:
  <listing> → root
  <dataSource> → PHP provider
  <listingColumns> → column definitions
  <massaction> → bulk operations

Column Settings:
  filter: text, select, dateRange, number
  dataType: text, select, date, number
  class: PHP column class for rendering

Mass Action:
  url: controller path
  confirm: confirmation dialog
  options: action parameters