Magento 2: рендерер для ячейки грида

Выход версии 2.3.0 приблизил использование PWA на фронте Magento-приложений на расстояние вытянутой руки. И если для фронта видны какие-то подвижки в применяемых технологиях, то с админкой всё гораздо стабильнее — старый добрый лабиринт из различных типов файлов, которые нужно поредактировать, чтобы на UI проявилось что-то полезное, усовершенствовать не планируется. В этой статье я описываю создание собственного рендерера для колонки грида в админке — вещи довольно несложной и, в то же самое время, довольно полезной при правильном применении. Например, рендерер для формирования в гриде заказов ссылки на карточку клиента, оформившего заказ:

image

«Родной» рендерер для ссылок в Magento состоит из двух файлов:

В процессе обработки шаблона используются функции, предоставляемые кодом (объект $col). Входными данными для обработки являются также текущая строка грида (объект $row):

Данные для грида загружаются через провайдер данных. Типовой запрос примерно такой:»http://…/admin/mui/index/render/? namespace=sales_order_grid…». Структуру данных можно увидеть через панель инструментов разработчика в браузере. Для грида заказов она примерно такая:

{
  "items": [
    {
      "id_field_name": "entity_id",
      "entity_id": "1",
      "status": "pending",
      "store_id": "Main Website   Main Website Store      Default Store View",
      "store_name": "Main Website\nMain Website Store\n",
      "customer_id": "1",
      "base_grand_total": "RUB34.68",
      "base_total_paid": null,
      "grand_total": "RUB34.68",
      "total_paid": null,
      "increment_id": "000000001",
      "base_currency_code": "RUB",
      "order_currency_code": "RUB",
      "shipping_name": "Alex Gusev",
      "billing_name": "Alex Gusev",
      "created_at": "2018-12-22 19:35:19",
      "updated_at": "2018-12-22 19:35:20",
      "billing_address": "Street,Riga,R\u012bga,1010",
      "shipping_address": "Street,Riga,R\u012bga,1010",
      "shipping_information": "Flat Rate - Fixed",
      "customer_email": "alex@flancer64.com",
      "customer_group": "1",
      "subtotal": "RUB24.68",
      "shipping_and_handling": "RUB10.00",
      "customer_name": "Alex Gusev",
      "payment_method": "checkmo",
      "total_refunded": "RUB0.00",
      "signifyd_guarantee_status": null,
      "orig_data": null,
      "actions": {
        "view": {
          "href": "http:\/\/sample.local.flancer64.com\/admin\/sales\/order\/view\/order_id\/1\/",
          "label": "View"
        }
      }
    }
  ],
  "totalRecords": 1
}

Таким образом, для создания собственного рендерера нам нужно задать UI-компонент, состоящий из двух файлов:


  • JS-код компонента;
  • Knockout-шаблон компонента;

Моей текущей задачей является создание рендерера, который бы выводил в ячейку грида заказов ссылку на клиента, оформившего заказ. Для формирования ссылки на клиента мне нужно использовать идентификатор соответствующего клиента — customer_id. Можно написать свой собственный шаблон для рендеринга, но в данном случае меня вполне устраивает имеющийся шаблон (./module-ui/view/base/web/templates/grid/cells/link.html). Достаточно переписать JS-код, который бы возвращал нужный результат при вызове функций $col.getLink($row()) и $col.isLink($row()).

Я разделил свой код на две части. Файл base.js содержит базовую логику для формирования ссылки, используемой в шаблоне, а файл customer_name.js позволяет настраивать базовую логику формирования ссылки в соответствии с задачами конкретного столбца.


Базовый функционал

В качестве базы я беру существующий UI-компонент column:

define([
    "Magento_Ui/js/grid/columns/column",
    "mageUtils"
], function (Column, utils) {
    ...
}

и (пере)определяю его атрибуты, указывая, что для рендеринга используется шаблон ui/grid/cells/link (из модуля Magento_Ui):

    return Column.extend({
        defaults: {
            /**
             * Replace idAttrName & route in children.
             */
            /* name of the identification attribute */
            idAttrName: "customer_id",
            /* route part to the page */
            route: "/customer/index/edit/id/",
            bodyTmpl: "ui/grid/cells/link"
        }
    });

а затем (пере)определяю методы, используемые в шаблоне.

isLink (ссылку можно сформировать, если данные record содержат атрибут с именем, хранящимся в this.idAttrName):

        isLink: function (record) {
            const result = !!utils.nested(record, this.idAttrName);
            return result;
        }

getLink:

        getLink: function (record) {
            const id = utils.nested(record, this.idAttrName);
            const result = ROOT_URL + this.route + id;
            return result;
        }


Ссылка на карточку клиента

В файле customer_name.js базовый функционал переопределяется таким образом, чтобы формировалась ссылка на карточку клиента «http://…/admin/customer/index/edit/id/…» на основании идентификатора клиента customer_id:

define([
    "Flancer32_GridLink/js/grid/column/link/base"
], function (Column) {
    "use strict";

    return Column.extend({
        defaults: {
            idAttrName: "customer_id",
            route: "/customer/index/edit/id/"
        }
    });
});


Подключение рендерера

Кастомный рендерер подключается к гриду в файле с определением соответствующего UI-компонента. В нашем случае это ./module-sales/view/adminhtml/ui_component/sales_order_grid.xml. В собственном модуле создается файл ./view/adminhtml/ui_component/sales_order_grid.xml в котором переопределяем рендерер для соответствующего столбца:

    
        
            
                true
            
        
    

Опция settings/visible нужна для того, чтобы колонка «customer_name» была видима в гриде (по-умолчанию она не видна).


Порядок загрузки

При сборке воедино всех xml-дескрипторов различных частей приложения в Magento (в том числе и описание UI-компонентов) важен порядок обработки дескрипторов, относящихся к одним и тем же компонентам, но находящимся в разных модулях. В нашем случае это ./view/adminhtml/ui_component/sales_order_grid.xml. Если платформа сначала обработает дескриптор из нашего модуля, а потом из sales-модуля, то при слиянии дескрипторов конфигурация sales-модуля заместит нашу конфигурацию в тех местах, где определяются одни и те же атрибуты (так, параметр settings/visible будет равен «false»), хотя рендерер все равно будет использоваться наш (sales-модуль не определяет рендерер для ячейки «Customer Name»).

Порядок загрузки прописывается в ./etc/module.xml:


    
        
            
        
    

В этом случае наш модуль будет загружаться после модуля «Magento_Sales» и наши настройки, в случае совпадения с настройками в sales-модуле, заместят настройки sales-модуля.


Резюме

Предоставляемый Magento платформой набор рендереров довольно базовый (например, не нашёл рендерера для целых чисел с выравниванием по правому краю), но создание собственных рендереров может оживить стандартный вид Magento-грида в админке.

Код данной публикации оформлен в виде модуля «mage2_ext_grid_column_renderer».

© Habrahabr.ru