Абсолютно все пользователи Magento 2 обратили внимание на обновленный интерфейс админ панели. В этой статье я хотел бы рассмотреть новый интерфейс Grid страниц и главное, как можно создать свою собственную Grid страницу с подробным описанием.
Magento 2 обладает 2мя типами Grid страниц. Тем, к которым мы привыкли в Magento 1 и абсолютно новым, Ui Grid, если я могу их так называть, которые основаны на новых Ui элементах.
Это довольно стандартная grid станица, она практически такая же как в Magento 1, а теперь перейдем к Ui Grid.
Вы возможно заметили много новых элементов на этой странице, в то время как Magento 1 экран выглядит обычно вот так:
Куда делись фильтры, вы можете спросить, чтобы их увидеть просто нажмите кнопку «Filters».
Как администратор вы можете не только просматривать записи из базы данных, как это было в Magento 1, но и модифицировать список столбцов, их позиции, список доступных фильтров и многое другое прямо из админ панели.
Кстати говоря, это так же работает на EAV Grid страницах (вроде списка товаров или списка пользователей). Добавив новый атрибут, вы можете добавить колонку с его значением.
Вы так же можете сохранить ваши изменения для того, чтобы вернуться к ним позднее или просто переключаться между разными сохраненными состояниями для выполнения тех или иных действий.
Если у вас на странице очень много записей, а вы прокрутили страницу довольно далеко, то заголовки полей и необходимые кнопки будут отображаться сверху.
Другая приятная особенность это полнотекстовый поиск на grid страницах (можете посмотреть CMS grid страницу или страницу со списком пользователей).
Вы можете ввести любой текст туда и если нашлась хоть 1 запись с аналогичным контентом, то она будет показана.
Еще 1 крутая вещь – это наконец-то добавленные колонки с изображениями. Вы можете увидеть пример такого столбца на странице со списком продуктов. По клику на изображении будет показана полная версия изображения этого продукта.
Последняя фича, о которой я хочу рассказать – это инлайн редактор. Другими словами, теперь если вы нажмете на строчку, то вы сможете ее отредактировать не открывая страницу редактирования.
Вы так же можете это делать через редактирование нескольких записей (mass action). Просто отметьте необходимые строки и выберите «edit» в меню «Actions».
Благодаря новой архитектуре админ панели Magento, все эти действия не требуют перезагрузки страниц. Это означает, что вы увидите результат ваших действий практически мгновенно.
Все новые фичи выглядят многообещающе, но как же их использовать? Это немного сложный вопрос по причине не достатка деталей, полных примеров кода в официальной документации (она сейчас в процессе заполнения, что хорошо). Это бы помогло разработчикам внедрять новые фичи быстрее и полностью понимать что же делает их код, а не в слепую копировать из гугла. Для того, чтобы исправить это, давайте просмотри полный процесс внедрения Ui Grid в абстрактный экстеншен.
Прежде всего, наш экстеншен должен иметь примерно следующую структуру:
* {entity_grid_listing} это уникальный идентификатор вашей конфигурации ui component, Magento мерджит xml файлы по имени, хорошая идея именовать их как {entity}_grid_listing, как сделано в CMS страницах (page_grid_listing).
В примере:
Список файлов должен быть знаком Magento разработчикам, новые файлы среди них это:
И так же пара новых строчек в следующих файлах конфигураций:
Давайте быстро пройдемся по основным файлам.
registration.php, module.xml должны содержать информацию для объявления нашего модуль, контент файлов вы можете увидеть в любом Magento 2 экстеншене.
acl.xml, menu.xml, routes.xml должны иметь информацию о ссылках и меню в админ панели, чтобы можно было добраться до вашей Grid страницы.
Index.php Controller – обычный админ контроллер, не обладающий никакими особенными методами.
InstallSchema.php – должен обладать инструкциями для того, чтобы создать необходимые таблицы, которые в дальнейшем будет использовать ваш модуль.
Ваши Model, ResourceModel и Collection model могут не иметь каких-то особенных методов, но должны обладать обычными методами, чтобы связать вашу модель с ресурс моделью, ресурс модель с БД и модель коллекции с ними обоими.
uigrid_index_index.xml — layout файл. Обратите внимание на контейнер с именем «content». Это самая важная вещь в этом файле. Имя тега uiComponent должно соответствовать имени вашего {entity_grid_listing}.xml файла в ui_component папке.
di.xml — содержит информацию о data source collection для вашего Ui Component.
Эта информация будет использована Magento для того, чтобы подготовить данные для вашей Grid страницы. Проще говоря, указанный в di.xml класс — это просто коллекция с несколькими дополнительными методами для работы с search criteria и так далее. Давайте посмотрим на этот класс по ближе.
Обратите внимание, что коллекция должна имплементить Magento\Framework\Api\Search\SearchResultInterface интерфейс и расширять вашу оригинальную коллекцию (на самом деле это делает работу с данными проще и вам не придется внедрять множество других методов). Все методы и свойства за исключением _construct могут быть скопированы из Magento\Cms\Model\ResourceModel\Block\Grid\Collection, больше они вам не понадобятся. Метод _construct особенный. Вы должны сделать так, чтобы коллекция использовала Magento\Framework\View\Element\UiComponent\DataProvider\Document объект как модель и вашу ресурс модель как, собственно, ресурс модель для общения с БД.
Ui Component — это ui_component/{entity_grid_listing}.xml файл, который предоставляет информацию о grid таблице и о том как данные должны быть в ней представлены.
С начала вам следует посмотреть module-cms/view/adminhtml/ui_component/cms_block_listing.xml файл, он выглядит относительно простым, но отсутствие описания в документации делает свое дело. Большинство ui grid страниц имеют схожую структуру такого файла: argument, dataSource, listingToolbar, columns.
Но что они на самом деле делают? Важен ли порядок элементов? Какие параметры можно и нужно передавать? И самый главный, как же все это работает?
Ui Component – это новая особенность Magento 2, это смесь knockoutjs и бекенд кода. Когда вы используете uiComponent тег в вашем лаяуте это говорит Magento что надо обработать файл с таким то именем определенным способом. Вкратце, Magento читает компонент файл, создает определенные классы, для того, чтобы собрать опции для компонента и в конечном итоге подготавливает jsLayout конфиг, который будет передан на фронтенд и обработан knockoutjs (будут созданы observables, viewModels, создан мапинг view теплейтов и так далее). Magento_Ui – это тот экстеншен, который предоставляет большинство готовых к использованию компонентов (viewModels), которые вы можете использовать в своем коде. Вы можете найти их в module-ui/view/base/web/js/*. Главный же конфиг – это module-ui/view/base/ui_component/etc/definition.xml, он содержит описание и дефолтные опции для всех компонентов, которые вы можете использовать в вашем Ui Component. Любые изменения в этом файле (или вашем definition.xml файле) будут применены ко всем экстеншенам.
Разберем Test/UiGrid/view/adminhtml/ui_component/uigrid_grid_listing.xml. Для того, чтобы было проще проследить структуру я буду нумеровать вложенные элементы и выделять основные места.
Начнем с самого первого элемента, который мы видим в примере выше.
1. <argument name="data" xsi:type="array">.
<item name="js_config" xsi:type="array"> содержит информацию о data provider на фронтенде, формат имени провайдера должен быть {file_name}.{file_name}_data_source.
<item name="spinner" xsi:type="string"> содержит ссылку на список столбцов в этом же файле, значение должно быть идентично имени, которое вы указали для тега columns. Я рекомендую называть его {extension}_{entity}_columns. Если вы не установили его или установили его не верно, то Magento не остановит spinner даже если данные уже загрузились.
<item name="buttons" xsi:type="array"> содержит информацию о верхних кнопках.
Обратите внимание, что вы можете не только добавить кнопку «Add …», но и другие кнопки с различными классами, как показано ниже.
Кнопка может быть добавлена не только через xml, но и через отдельный класс. Обратите внимание на закомментированный кусок кода. Реализацию этих классов вы найдете внутри них самих.
2. <dataSource name="uigrid_grid_listing_data_source">
Эта секция содержит важную информацию о render url, data provider классе, имени вашей коллекции, которая предоставляет данные и так далее. Имя атрибута должно следовать следующему формату {file_name}_data_source и должно быть идентично тому, которое вы использовали ранее.
Вам необходимо изменить только следующие элементы:
<argument name="name" xsi:type="string"> должен содержать имя вашей коллекции в di.xml,
<argument name="primaryFieldName" xsi:type="string">, <argument name="requestFieldName" xsi:type="string">, <item name="indexField" xsi:type="string"> – entity id ключ вашей таблицы в БД.
Остальные атрибуты могут оставаться такими же как в примере.
Если имя задано не верно или коллекция не была описана в di.xml вы увидите следующую ошибку
3. <listingToolbar name="listing_top">
Этот элемент содержит список элементов верхнего меню, таких как Filters, Bookmarks, Column editor, Full text search field, Mass Actions, Pagination и так далее.
Имейте в виду, что вы можете заполнять эту xml в нескольких экстеншенах одновременно! Просто поместите ui_component файл с тем же именем в тот же или base scope. Порядок элемент играет большую разницу, поэтому следите за тем в каком порядке загружаются модули и элементы добавляются в ui_component. Если <listingToolbar> будет загружен после <columns>, вы получите следующий результат:
Имя элемента должно быть как указано примере.
3.1. <item name="sticky" xsi:type="boolean"> опциональный, вы можете пропустить его. Значение по умолчанию «false». Этот параметр отвечает за быстрый доступ к топ меню во время прокрутки страницы, оно будет следовать за скролом, пока вы не прокрутите страницу обратно к самому верху.
3.2. <bookmark name="bookmarks"> опциональный. Он добавляет кнопку «Bookmark». Если вы добавите этот элемент, Magento позволит администраторам сохранять состояние столбцов и их позиции для использования позже. У каждого администратора свой собственный список.
3.3. <columnsControls name="columns_controls"> опциональный. Он добавляет кнопку «Columns». Если вы добавите этот элемент, Magento позволит администраторам добавлять или удалять некоторые столбцы из вашей grid таблицы.
3.4. <filterSearch name="fulltext"> опциональный. Добавляет full text search поле.
Magento разработчики внедрили замечательную фичу — поиск по любому полю в БД без написания дополнительного кода! Все что вам нужно сделать, это добавить full text index по 1 или нескольким столбцам в БД. Если у вашей таблицы есть хоть 1 full text index то введенный текст будет искаться по нему. Вы можете добавлять индексы в ваших инстал скриптах. Начиная с MySQL 5.6.4 InnoDB таблицы поддерживают Full text Index так же как и MyISAM.
3.5. <filters name="listing_filters"> опционален. Этот элемент может содержать дополнительные микронастройки для фильтров и их отображения. В примере вы можете видеть <argument> и <filterSelect> элементы.
Давайте начнем с первого.
<argument>
Иногда вам может понадобиться изменить компонента или шаблон для определенного типа фильтра (например изменить поведение text input внутри списка фильтров или select элемент). Наиболее частый случай в Magento 2 коде это замена стандартного компонента и шаблона select дропдауна с select на ui-select для status фильтра.
Обратите внимание, что это изменение затронет все фильтры <item name={type}> типа.
<filterSelect>
Элемент «filterSelect» — это пример изменения стандартного фильтра для store_id колонки. В общем практически все столбцы имеют свой собственный фильтр (text, textRange, date, select и т.д.), но в некоторых случаях вам необходимо переопределить поведение/отображение такого фильтра для некой колонки. Доступные типы: filterInput, filterRange, filterSelect и containerConfiguration (об этом типе нам говорит сообщение в ошибке, если вы попробуете указать что-то другое). Имя должно быть идентично имени столбца, фильтр, которого вы хотите переопределить, в противном случае мапинг не будет работать.
3.6. <massaction name="listing_massaction"> элемент опционален. Он добавляет massaction дропдаун и всплывающее сообщения если пользователь не выбрал никакие строки до выбора действия.
Обычно этот элемент выглядит как обычный дропдаун, но вы можете заменить компонент на древообразное меню.
Если вы хотите заменить дефолтное сообщение «You haven’t selected any items!» как показано выше, вам надо передать следующие параметры в massaction component, просто вставьте свое сообщение в «noItemsMsg».
Для того, чтобы добавить новое действие в дропдаун, взгляните на пример ниже. Это пример действия «delete», но вы можете добавить так же другие.
<action name="delete"> — должен иметь уникальное имя, так как Magento мерджит элементы по имени.
<item name="type"> — должен быть уникальным так же, в противном случае Magento будет показывать все такие опции в дропдауне, но все они будут выполнять 1 и тоже действие как было описано в 1ом элементе с этим типом так как Magento кеширует конфиги по типу. Хорошей практикой считается использование того же имени, что вы указали для экшена.
<item name="label"> — имя опции.
<item name="url"> — урл действия, который будет использован для обработки выбранных строк. Туда будет отправлен массив selected/excluded элементов, примененные фильтры и примененная full text search фраза. Разница между передаваемыми параметрами зависит от метода выбора элементов. Если вы нажали «select all» то элемент «excluded» будет содержать «false». Если вы выбрали несколько несколько элементов вручную, массив «selected» будет содержать entity id всех выбранных записей. Самый последний случай, если вы нажали «select all», но позже анчекнули несколько записей вручную, массив «excluded» будет содержать entity id всех анчекнутых записей. Чтобы посмотреть пример реализации «massDelete» экшена и как эти параметры обрабатываются посмотрите класс Magento\Cms\Controller\Adminhtml\Block\massDelete.
<item name="confirm"> — опциональный элемент. Если указан, Magento будет показывать модальное окно для подтверждения действия с «Ok» или «Cancel» кнопками. Title и Message могут быть изменены как показано выше.
Сейчас давайте рассмотрим не обычную кнопку, а mass edit кнопку.
Основная разница между ними это <item name="callback"> элемент. Он опционален. Его параметры делают возможным редактирование нескольких строк сразу. По факту, он применяет колбек к выбранным строкам.
Вот так изменяется грид если выбрано несколько строк:
и если выбрана только 1 стока:
Для подобного редактирования будут доступны только те колонки, которые имеют «editor» атрибут (больше информации о нем ниже).
<item name="provider"> — это путь до компонента. Обратите внимание на строку в примере. Значение должно следовать следующему формату {filename}.{filename}.{ columns_element_name}_editor.
<item name="target"> — это имя метода внутри knockoutjs компонента, «editSelected» должен быть указан тут.
Детальная конфигурация редактора будет рассмотрена чуть позже.
Говоря об опциях massaction дропдауна, как вы видели раньше, там доступно 2 типа опций. Обычные (select) и древоподобные опции. К несчастью «select» компонент не поддерживает подменю, но tree-massactions поддерживает. Для применения этого компонента вам надо сказать Magento использовать Magento_Ui/js/grid/tree-massactions компонент. «Action» элемент должен быть уже знаком вам, поэтому давайте взглянем на минорные изменения в следующем примере.
<argument name="actions" xsi:type="array"> опционален. Он содержит массив элементов с именами от 0 до N, если имена не будут следовать целочисленной последовательности то knockoutjs (javascript) выбросит ошибку.
<param name="…">…</param> так же опционален. Пока вся информация о выбранных строках будет передана в теле post запроса, эти параметры будут переданы как get параметры и зависят только от выбранной опции (см. пример выше). Эти параметры могут быть использованы и с другими масс экшенами.
3.7. <paging name="listing_paging"/> опциональный элемент. Он добавляет пагинацию для вашей грид страницы. Если он не был добавлен, Magento будет показывать все записи на 1 станице и не будет показывать количество найденных записей.
С элементом:
без элемента:
3.8. <exportButton name="export_button"/> опциональный элемент. Этот компонент добавляет кнопку export с 2мя опциями: export as csv, export as xml. Вам не надо имплементить дополнительную логики, чтобы эта фича работала. Она генерирует фид файл содержащий только доступные данные, согласно примененным фильтрам. Файл игнорирует сорт ордер и видимость элементов на экране, Magento всегда генерирует файл включающий все колонки из ui_component файла. Колонки будут в порядке их появление в этом файле, полностью игнорируя иную сортировку (включая атрибут сортировки элементов в файле). Вы так же можете добавить другие форматы для экспорта, как это сделать описано в документации devdocs.magento.com/guides/v2.1/ui-components/ui-export.html.
4. <columns name="uigrid_grid_columns">
Это наиболее интересная и важная часть для отображения колонок в гриде. Этот элемент содержит список столбцов, которые должны быть доступны админу.
<columns name="uigrid_grid_columns"> — имя элемента должно быть следующего формата {extension}_{entity}_columns и быть идентично тому, что вы прописали в <item name="spinner" xsi:type="string">name_of_columns_element</item>. Обычно этот тег имеет только атрибут «name», но может так же иметь и «class» как в vendor/magento/module-catalog/view/adminhtml/ui_component/product_listing.xml.
<columns name="product_columns" class="Magento\Catalog\Ui\Component\Listing\Columns">
Вам нужно использовать класс в элементе columns только если вы хотите обрабатывать какие-то данные динамически вроде сортировки, видимости каких-то колонок или же добавлять новые столбцы динамически.
Если вы хотите добавить «edit» массэкшен в список массэкшенов или сделать доступным инлайн редактор вам необходимо сперва его сконфигурировать.
<item name="selectProvider" xsi:type="string"> — путь к колонке/компоненту в дереве, придерживайтесь следующего формата:
{filename}.{filename}.{columns_name}.{selectionsColumn_name},
в примере это uigrid_grid_listing.uigrid_grid_listing.uigrid_grid_columns.ids.
<item name="enabled" xsi:type="boolean"> — включить/выключить редактор.
<item name="indexField" xsi:type="string"> — entity id, будет использоваться при сохранении данных.
<item name="clientConfig" xsi:type="array"> — конфигурация «Save» экшена.
<item name="saveUrl" xsi:type="url" path="*/*/inlineEdit"/> — урл, который knockoutjs использует для сохранения инлайн изменений. Обратите внимание на «path», я специально указал урл как "*/*/inlineEditor", чтобы показать, что такие урлы так же поддерживаются.
<item name="validateBeforeSave" xsi:type="boolean"> — это весьма интересная опция. Дефолтное значение – «true», так что если вы пропустили эту настройку и не указали следующий параметр «validateUrl», knockoutjs выбросит ошибку. Если эта настройка включена, knockoutjs отправляет новые значения на «validateUrl» и если респонс в порядке (например http код 200), knockoutjs отправит эти же данные на saveUrl, в противном случае покажет сообщение с ошибкой. Если вам не нужен этот функционал и вы просто хотите сохранять данные и возможно валидировать их прямо там то установите параметр «false».
<item name="validateUrl" xsi:type="url" path="*/*/checkData"/> — урл для валидации данных.
Если вы хотите активировать инлайн редактор по клику на строчку (например как на CMS page/block гридах), вам необходимо добавить конфиг в <argument> вашего <columns> тега сразу после «editorConfig». Единственный параметр, который вам надо поменять это «provider», он должен следовать следующему формату {filename}.{filename}.{columns_name}_editor, все остальные параметры должны быть как в примере ниже.
По определенным причинам инлайн редактор может не подойти вам. В таком случае вы можете захотеть выполнять другие действия по клику на строчку. Для этого, поместите следующий код вместо вызова inlineEditor. Вам необходимо изменить только 2 параметра там: provider,0. Провайдер должен следовать следующему формату {filename}.{filename}.{columns_name}.actions, имя экшена из вашего «action» списка (см. ниже).
<column|actionsColumn|selectionsColumn> — все эти элементы расположены внутри <columns> тега, они имеют схожий синтаксис. <column> используется для добавления обычной колонки, <actionsColumn> используется для добавления столбца «action» и наконец <selectionsColumn> используется для добавления колонки с чекбоксами для выбора строк. <actionsColumn> может быть пропущен если вы хотите использовать только инлайн редактор. Имя selectionsColumn атрибута должно быть ids, он не имеет атрибута class и может быть пропущен если вы не хотите использовать экспорт, инлайн редактор, масс экшены и т.д.
<column name="{unique_name}"> — это обязательный атрибут. Это уникальное имя столбца. Magento перезаписывает столбцы по имени. Имя столбца может быть не идентично имени колонки в БД (ключу в вашей коллекции), это лишь имя колонки. Если же имя колонки идентично имени колонки в БД, Magento замапит данные из коллекции в это поле автоматически и эти данные будут доступны (видимы) в гриде. В противном случае необходимо использовать атрибут «class», чтобы получить/подготовить необходимое значение.
<column class="{class_name}"> — это опциональный атрибут. Главная особенность «класса» это форматирование/подготовка данных из коллекции для отображения в колонке/использования компонентом. Класс имеет доступ к данным коллекции для этой строки и может модифицировать любое значение как и добавлять/удалять некоторые ключи. Класс Magento\Ui\Component\Listing\Columns\Date форматирует дату из БД, приводит ее к необходимому формату и так же применяет сдвиг для тайм зоны. Класс Magento\Catalog\Ui\Component\Listing\Columns\Thumbnail предоставляет данные для тамбнейл компонента. Посмотрите их код, чтобы лучше понять как они работают.
<argument name="data" xsi:type="array"> — это обязательный тег если вы хотите предоставить дополнительные данные в класс вашего столбца (будут доступны все данные внутри тега) или в его компонент (будут доступны все данные внутри внутреннего «config» тега).
<item name="options" xsi:type="object"> — опциональный элемент. Нативно используется только с dataType «select» (см. дальше) для отображения опций из source модельки, но вы можете использовать этот параметр для обработки данных в вашем классе (они имеют полный доступ ко всем данным внутри «data» тега, но эти данные не будут доступны в knockoutjs компоненте). Так же есть и другие способы сделать тоже самое, см. ниже.
<item name="config" xsi:type="array"> — обязателен если вам нужно передать какие-либо данные в компонент класс и/или knockoutjs компонент. Вы можете иметь полный доступ к этим данным внутри вашей knockoutjs ViewModel. По умолчанию, ViewModel не имеет доступа к параметрам за пределами «config» тега.
<item name="component" xsi:type="string"> — опциональный. Проще говоря, компоненты рендерят значения для отображения в колонках. На пример, один из них отвечает за отображение «Sep 5, 2016 8:03:07 PM» вместо 2016-09-05 в колонке даты. Значение по умолчанию – это Magento_Ui/js/grid/columns/column, он же дефолтный компонент для всех колонок. ViewModel’и для рендеринга колонок расположены в Magento_Ui/js/grid/columns/. Наиболее используемые значения (компоненты) в этом теге:
Magento_Ui/js/grid/columns/column – отображает значение как текстовое, т.е. как есть,
Magento_Ui/js/grid/columns/date – отображает даты согласно указанному формату,
Magento_Ui/js/grid/columns/select – отображает значения как выбранные селект опции с мапингом значений и их лейблов,
Magento_Ui/js/grid/columns/thumbnail – показывает изображение в колонке,
Вы так же можете создать свои собственные компоненты, просто «наследуйтесь» от Magento_Ui/js/grid/columns/column.
<item name="bodyTmpl" xsi:type="string"> — опциональный. Вы можете изменить шаблон («view») для значения, который будет использоваться в столбце. Дефолтное значение ui/grid/cells/text. Если данные не могут быть трансформированы в текст и вам нужно больше возможностей для использования html внутри, используйте шаблон ui/grid/cells/html (он обычно используется в Store Id колонках) или любой подходящий из ui/grid/cells (или вашего экстеншена).
<item name="add_field" xsi:type="boolean"> — опциональный. Вы могли видеть этот тег в некоторых ui_*.xml файлах, он требует дополнительной реализации в DataProvider/collection классах и обязателен для eav/значений из отдельных таблиц только так как такие столбцы могут быть не найдены в основной таблице без этого вызова.
<item name="sortable" xsi:type="boolean"> — опциональный. Дефолтное значение «true». Он отключает способность применять сортировку по клику на столбце.
<item name="filter" xsi:type="string"> — опциональный. Этот параметр добавляет фильтр к колонке. Он поддерживает следующие значения: textRange, dateRange, select, text. Обратите внимание на скриншот ниже. (ID – textRange, Created – dateRange, Store View – кастомный фильтр, Name – text, Status – select).
Если вам надо использовать кастомный фильтр для колонки (например селект с группами, основанный на кастомной модельке, вроде списка Website/StoreView) вы можете пропустить фильтр параметр в списке параметров вашей колонки и добавить описание фильтра в <filters name="listing_filters">.
<item name="sorting" xsi:type="string"> — опционанальный, он применяет сортировку ко всему гриду по этому полю. Доступные следующие опции: asc, desc. Только к 1 полю может быть применена сортировка по умолчанию.
<item name="label" xsi:type="string"> — обязательное. Вкратце, это имя вашей колонки, оно будет отображаться в хедере вашей колонки. По факту, это просто текст и используется «ui/grid/columns/text» шаблон, который указан в «headerTmpl» параметре. Вы можете изменить его, если вам надо.
<item name="visible" xsi:type="boolean"> — опциональный. Дефолтное значение «true». Этот параметр позволяет скрыть колонку из грида, но она будет доступна в списке доступных колонок, ее можно будет добавить оттуда.
<item name="draggable" xsi:type="boolean"> — опциональный. Дефолтное значение «true». Делает столбец статичным/не перемещаемым.
<item name="editor" xsi:type="{string|array}"> — опциональный. Позволяет использовать инлайн едитор для колонки. Если тег пропущен то значение в этом столбце нельзя будет редактировать при вызове инлайн едитора по клику на строке или через масс экшен меню. Есть 2 способа применения этого тега. Он может иметь тип «string» или тип «array». Если вам надо включить едитор для этого поля то используйте «string» и укажите тип (режим) для этого поля, но если вы хотите сконфигурировать едитор более точно то используйте тип «array». Всего есть 3 режима: text, date, select. Вы должны выбрать 1 из них.
Список настроек для едитора:
<item name="timezone" xsi:type="boolean"> — опциональный. Дефолтное значение «true». Эта опция применима только к колонкам типа «date». Она используется в Magento\Ui\Component\Listing\Columns\Date классе. Позволяет скорректировать тайм зону если в БД и в админ панели у вас используют разные тайм зоны.
<item name="dataType" xsi:type="string"> — опциональный. В реальной жизни, полезен только со столбцами типа «select». Дефолтное значение «text». Доступные значения любые сущности(теги) из /vendor/magento/module-ui/view/base/ui_component/etc/definition.xml. Что такое dataType? Проще говоря, это дефолтное поведение ваших элементов. Когда Magento начинает обрабатывать конфиг вашего столбца, она читает dataType параметр, загружает его описание из definition.xml, запускает объект класса, который указан для этого dataType («class» аттрибут). Этот объект имеет полный доступ к параметрам, переданным в «data» тег и может модифицировать их. После обработки этих данных Magento мерджит конфиг из definition.xml, данными сгенерированные указанным объектом с вашим описанием колонки и передает эти данные на фронтенд, где knockoutjs начинает обрабатывать полученный конфиг. Относительно грида, единственный полезный dataType это «select» благодаря классу Magento\Ui\Component\Form\Element\Select, который связан с ним. Этот класс обрабатывает тег «options» и форматирует данные из указанной source model в подходящий массив опций, которые могут быть в дальнейшем обработаны Magento_Ui/js/grid/columns/select (нативный select компонент).
<item name="sortOrder" xsi:type="number"> — опциональный. Если sortOrder пропущен, Magento отображает столбцы в порядке их описания в ui_component файле. Если же этот параметр присутствует, то Magento отображает элементы согласно sortOrder параметру, но в экспорт файле порядок колонок будет идентичен порядку элементов в ui_component файле! Имейте в виду, что после первого раза, как админ откроет вашу грид страницу порядок элементов будет сохранен в БД и любые изменения sortOrder параметра не будут применены. Более того, новые колонки всегда будут добавлены в самый конец. Подробнее об этом вы найдете ниже.
<item name="options" xsi:type="array"> — опциональный и является альтернативным способом рендеринга колонки типа «select». Может быть использован с «select» компонентом. Ранее было сказано, что для отображения лейблов вместо ключей из БД вам надо использовать «option» тег с сорс моделькой и указать dataType=«select». Другой способ так же существует. «select» компоненту нужен массив опций для того, чтобы отобразить лейблы вместо id. Если в случае с сорс моделькой dataType элемент подготавливает значения, вы можете так сформировать необходимый массив опций вручную. Обратите внимание на синтаксис:
Каждый айтем это опция/маппинг. Вместо {value} будет отображено {option_label}. Это довольно удобный способ, но если у вас уже есть сорс моделька для вашего дропдауна использование dataType подхода более оправдано.
<item name="has_preview" xsi:type="boolean"> — опциональный. Применим только с «thumbnail» компонентом/столбцами. Дефолтное значение «false». Если он включен тогда по клику на изображении в гриде будет показано модальное окно с большим изображением и ссылкой на страницу редактирования.
Для того, чтобы посмотреть все доступные параметры и какие возможности есть у каждого из компонентов вы можете посмотреть их исходный код.
Этот столбец просто отображает данные с именем «data» из БД как есть. Он не имеет фильтра или инлайн редактора.
Это довольно важный столбец. Он предоставляет не только «select all», «select all on this page», «deselect all», «deselect all on this page», чекбоксы, но и маппинг строк и их id. Практически всегда описывается первым.
<selectionsColumn name="ids"> имя должно быть «ids».
<item name="indexField" xsi:type="string"> имя primary key в БД.
Этот столбец показывает значения как есть из БД, но так же обладает простым текстовым фильтром и поддерживает инлайн редактор.
Есть 2 режима для отображения и инлайн редактора. Date и datetime.
Класс Magento\Ui\Component\Listing\Columns\Date позволяет скорректировать тайм зону для данных из БД к выбранной локали.
Компонент Magento_Ui/js/grid/columns/date предоставляет необходимый функционал для отображения дат.
<item name="editor" xsi:type="array"> устанавливает инлайн редактор для поля.
<item name="showsTime" xsi:type="boolean"> — опциональный. Устанавливает режим. Дефолтное значение «false». Если вы хотите заставить Magento показывать селектор времени то установите значение в «true». Если вы хотите отображать корректную дату в инлайн редакторе вам необходимо установить showTime = true, в противном случае дата будет сбрасываться на сегодняшний день при запуске инлайн едитора – это баг Magento 2.
<item name="timezone" xsi:type="boolean"> — опциональный параметр. Дефолтное значение «true». Если вам надо отключить коррекцию времени укажите этот параметр и передайте «false», в противном случае она будет применена. Учтите, что время в инлайн редакторе будет отображаться с учетом тайм зоны (если не отключено) и когда вы нажмете на «save» на сервер отправится именно это время.
<item name="filter" xsi:type="string">dateRange</item> — опциональный. Добавляет фильтр в список фильтров. Имейте в виду, он не зависит от настроек редактора, дефолтный фильтр для DataRange отображает только даты.
<item name="dateFormat" xsi:type="string"> — опциональный. Позволяет указать формат для отображения даты в столбце. Дефолтное значение «MMM d, YYYY h:mm:ss A», что эквивалентно «Sep 5, 2016 9:00:00 AM».
Наиболее распространенный столбец типа «select» это Status. Обычно он имеет всего 2 значения Enabled и Disabled.
<item name="options" xsi:type="object"> — обязательное для подхода с использованием сорс модели. Предоставляет массив значений (через сорс модель), но knockoutjs компонент не может использовать эти данные на прямую.
<item name="dataType" xsi:type="string"> — обязательное для этого подхода. Использует класс из «options» и получает список всех доступных значений. Далее «select» класс форматирует полученный массив опций для knockoutjs компонента. После чего компонент рендерит эти данные как «select».
Если у вас нет сорс модели и вы не хотите создавать ее вы можете предоставить список необходимых значений непосредственно в xml.
<item name="options" xsi:type="array"> — обязательное поле для подхода без использования сорс модели. Оно содержит массив ключ/значение.
В большинстве случаев Store View хранится как store_id (идентификатор стора), но показывать это как есть не самая лучшая идея. Для того, чтобы заменить это значение на имя стора надо использовать кастомный класс. Чтобы показать данные как на скриншоте выше надо использовать html, так как дефолтный шаблон отображает только текстовые значения. Надо изменить его в «bodyTmpl». Класс Magento\Store\Ui\Component\Listing\Column\Store заменяет идентификатор на структурированное Website-Store-StoreView html значение. Имейте в виду, что после этого так же надо применить кастомный фильтр, чтобы позволить фильтровать эти данные в таком же виде.
Thumbnail столбцы немного специфичные в имплементации. Компонент требует следующие данные:
*{column_name} это «image» в примере.
Эти данные редко хранятся в БД, для предоставления этих данных на странице продуктов используется Magento\Catalog\Ui\Component\Listing\Columns\Thumbnail. Посмотрите его исходный код, чтобы создать вашу собственную реализацию.
<item name="has_preview" xsi:type="boolean"> — опциональный. Включение этой опции позволяет показывать всплывающее окно по клику на изображении в столбце.
Столбец «Action» использует «actionColumn» тег вместо «column», но его особенности и синтаксис такие же. Столбец может быть создан 2мя способами.
Способ первый
Для создания такого «action» столбца используйте следующую короткую:
или полную запись:
На деле, они идентичны. Единственная разница это «indexField» элемент. По факту, этот параметр не очень важен и не затрагивает функциональность, там нет жизненно необходимых мест в его knockoutjs компонент коде. Так что я просто пропустил его в короткой форме, но это может не работать в будущих обновлениях после рефакторинга кода этого компонента.
Главная часть это класс, он возвращает список опций. Для имплементации класса вроде этого посмотрите Magento\Cms\Ui\Component\Listing\Column\BlockActions.php.
Magento отображает дропдаун «Select» если есть хотя бы 1 опция.
Способ второй
Так же можно добавить «action» столбец без создания новых классов.
Вы можете использовать «Magento\Sales\Ui\Component\Listing\Column\ViewAction» класс. Он очень полезен для многих случаев. Вам всего-то надо иметь конфиг вроде того, что показан выше и primary key полем в БД должно быть «entity_id».
<item name="indexField" xsi:type="string"> — см. выше,
<item name="viewUrlPath" xsi:type="string"> — урл страницы редактирования,
<item name="urlEntityParamName" xsi:type="string"> — имя entity_id поля, которое будет отправляться на страницу редактирования в качестве GET параметра. Дефолтное значение «entity_id», так что оно может быть пропущено, но если вы хотите отправлять что-то отличное от entity_id то укажите его как показано в примере.
На самом деле параметры для компонента могут быть предоставлены полностью через xml, но в таком случае вам надо будет указывать полный урл до страницы редактирования записи, что менее удобно.
Как только админ откроет грид страницу в первый раз Magento сохранит порядок столбцов, примененную сортировку данных, показанные элементы и так далее в ui_bookmark таблицу и последующие изменения в ui_component.xml не смогут изменить этого. Даже если вы в дальнейшем добавите новый столбец в начало файла или в середину, Magento будет отображать этот столбец в самом конце списка, даже если последний столбец был «actions» и он был отмечен как не перемещаемый, игнорируя sortOrder атрибут. Чтобы сбросить эти изменения вам понадобиться удалить все записи, которые имеют нейм спейс идентичный вашему гриду (имя файла) из БД (как минимум имеющие идентификатор «default», который применяется к новым пользователям, и «current» если вы хотите сбросить активные пользовательские изменения так же).
Подводя итог, я хотел бы сказать, что ui компоненты имеют массу возможностей. Благодаря knockoutjs и его внедрению в ui компоненты, разработчики могут создавать динамический контент без добавления дополнительных библиотек и обновления страниц как это было в Magento 1. Единственный недостаток здесь это то, что разработчикам необходимо потратить определенное время для понимания идеи и подхода для того, чтобы начать работать с новой фичей эффективно. Сама Magento 2, как и ее документация, продолжает развиваться каждый день. Прежде всего обратите внимания на это. Это хорошая идея начать ваше погружение в ui компоненты с оффициальной документации. Вы можете найти больше информации о Ui Component по ссылке или тут.
Оглавление
Обзор
Создание экстеншена
Ui Component
Editor
Columns
Examples
Необходимо помнить
Заключение
Обзор
Magento 2 обладает 2мя типами Grid страниц. Тем, к которым мы привыкли в Magento 1 и абсолютно новым, Ui Grid, если я могу их так называть, которые основаны на новых Ui элементах.
Это довольно стандартная grid станица, она практически такая же как в Magento 1, а теперь перейдем к Ui Grid.
Вы возможно заметили много новых элементов на этой странице, в то время как Magento 1 экран выглядит обычно вот так:
Куда делись фильтры, вы можете спросить, чтобы их увидеть просто нажмите кнопку «Filters».
Как администратор вы можете не только просматривать записи из базы данных, как это было в Magento 1, но и модифицировать список столбцов, их позиции, список доступных фильтров и многое другое прямо из админ панели.
Кстати говоря, это так же работает на EAV Grid страницах (вроде списка товаров или списка пользователей). Добавив новый атрибут, вы можете добавить колонку с его значением.
Вы так же можете сохранить ваши изменения для того, чтобы вернуться к ним позднее или просто переключаться между разными сохраненными состояниями для выполнения тех или иных действий.
Если у вас на странице очень много записей, а вы прокрутили страницу довольно далеко, то заголовки полей и необходимые кнопки будут отображаться сверху.
Другая приятная особенность это полнотекстовый поиск на grid страницах (можете посмотреть CMS grid страницу или страницу со списком пользователей).
Вы можете ввести любой текст туда и если нашлась хоть 1 запись с аналогичным контентом, то она будет показана.
Еще 1 крутая вещь – это наконец-то добавленные колонки с изображениями. Вы можете увидеть пример такого столбца на странице со списком продуктов. По клику на изображении будет показана полная версия изображения этого продукта.
Последняя фича, о которой я хочу рассказать – это инлайн редактор. Другими словами, теперь если вы нажмете на строчку, то вы сможете ее отредактировать не открывая страницу редактирования.
Вы так же можете это делать через редактирование нескольких записей (mass action). Просто отметьте необходимые строки и выберите «edit» в меню «Actions».
Благодаря новой архитектуре админ панели Magento, все эти действия не требуют перезагрузки страниц. Это означает, что вы увидите результат ваших действий практически мгновенно.
Создание экстеншена
Все новые фичи выглядят многообещающе, но как же их использовать? Это немного сложный вопрос по причине не достатка деталей, полных примеров кода в официальной документации (она сейчас в процессе заполнения, что хорошо). Это бы помогло разработчикам внедрять новые фичи быстрее и полностью понимать что же делает их код, а не в слепую копировать из гугла. Для того, чтобы исправить это, давайте просмотри полный процесс внедрения Ui Grid в абстрактный экстеншен.
Прежде всего, наш экстеншен должен иметь примерно следующую структуру:
- {NameSpace}/{ExtensionName}/registration.php
- {NameSpace}/{ExtensionName}/etc/module.xml
- {NameSpace}/{ExtensionName}/etc/di.xml
- {NameSpace}/{ExtensionName}/etc/acl.xml
- {NameSpace}/{ExtensionName}/etc/adminhtml/menu.xml
- {NameSpace}/{ExtensionName}/etc/adminhtml/routes.xml
- {NameSpace}/{ExtensionName}/Model/{Entity}.php
- {NameSpace}/{ExtensionName}/Model/ResourceModel/{Entity}.php
- {NameSpace}/{ExtensionName}/Model/ResourceModel/{Entity}/Collection.php
- {NameSpace}/{ExtensionName}/Model/ResourceModel/{Entity}/Grid/Collection.php
- {NameSpace}/{ExtensionName}/Setup/InstallSchema.php
- {NameSpace}/{ExtensionName}/Controller/Adminhtml/Index/Index.php
- {NameSpace}/{ExtensionName}/view/adminhtml/layout/{frontnameId}_index_index.xml
- {NameSpace}/{ExtensionName}/view/adminhtml/ui_component/{entity_grid_listing}.xml
* {entity_grid_listing} это уникальный идентификатор вашей конфигурации ui component, Magento мерджит xml файлы по имени, хорошая идея именовать их как {entity}_grid_listing, как сделано в CMS страницах (page_grid_listing).
В примере:
- {NameSpace} — Test,
- {ExtensionName} — UiGrid,
- {Entity} – Grid.
Список файлов должен быть знаком Magento разработчикам, новые файлы среди них это:
- {NameSpace}/{ExtensionName}/Model/ResourceModel/{Entity}/Grid/Collection.php
- {NameSpace}/{ExtensionName}/view/adminhtml/ui_component/{entity_grid_listing}.xml
И так же пара новых строчек в следующих файлах конфигураций:
- {NameSpace}/{ExtensionName}/view/adminhtml/layout/{frontnameId}_index_index.xml
- {NameSpace}/{ExtensionName}/etc/di.xml
Давайте быстро пройдемся по основным файлам.
registration.php, module.xml должны содержать информацию для объявления нашего модуль, контент файлов вы можете увидеть в любом Magento 2 экстеншене.
registration.php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Test_UiGrid',
__DIR__
);
module.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Test_UiGrid" setup_version="0.1.0"/>
</config>
acl.xml, menu.xml, routes.xml должны иметь информацию о ссылках и меню в админ панели, чтобы можно было добраться до вашей Grid страницы.
acl.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd">
<acl>
<resources>
<resource id="Magento_Backend::admin">
<resource id="Test_UiGrid::test" title="Test" translate="title" sortOrder="30">
</resource>
</resource>
</resources>
</acl>
</config>
menu.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
<menu>
<add id="Test_UiGrid::test" title="Test" translate="title" module="Test_UiGrid" sortOrder="20" dependsOnModule="Test_UiGrid" resource="Test_UiGrid::test"/>
<add id="Test_UiGrid::test_uigrid" title="UiGrid" translate="title" module="Test_UiGrid" sortOrder="10" parent="Test_UiGrid::test" action="uigrid" resource="Test_UiGrid::test"/>
</menu>
</config>
routes.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="admin">
<route id="uigrid" frontName="uigrid">
<module name="Test_UiGrid" />
</route>
</router>
</config>
Index.php Controller – обычный админ контроллер, не обладающий никакими особенными методами.
Index.php
namespace Test\UiGrid\Controller\Adminhtml\Index;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\App\Action\Action;
use Magento\Framework\View\Result\Page;
class Index extends Action
{
public function execute()
{
return $this->resultFactory->create(ResultFactory::TYPE_PAGE);
}
}
InstallSchema.php – должен обладать инструкциями для того, чтобы создать необходимые таблицы, которые в дальнейшем будет использовать ваш модуль.
Ваши Model, ResourceModel и Collection model могут не иметь каких-то особенных методов, но должны обладать обычными методами, чтобы связать вашу модель с ресурс моделью, ресурс модель с БД и модель коллекции с ними обоими.
Model
namespace Test\UiGrid\Model;
use Magento\Framework\Model\AbstractModel;
use Test\UiGrid\Model\ResourceModel\Grid;
class Grid extends AbstractModel
{
protected function _construct()
{
$this->_init(Grid::class);
}
}
ResourceModel
namespace Test\UiGrid\Model\ResourceModel;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
class Grid extends AbstractDb
{
protected function _construct()
{
$this->_init('uigrid', 'entity_id');
}
}
Collection
namespace Test\UiGrid\Model\ResourceModel\Grid;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use Test\UiGrid\Model\Grid;
use Test\UiGrid\Model\ResourceModel\Grid as GridResource;
class Collection extends AbstractCollection
{
protected function _construct()
{
$this->_init(Grid::class, GridResource::class);
}
}
Подготавливаем данные для Ui Component
uigrid_index_index.xml — layout файл. Обратите внимание на контейнер с именем «content». Это самая важная вещь в этом файле. Имя тега uiComponent должно соответствовать имени вашего {entity_grid_listing}.xml файла в ui_component папке.
uigrid_index_index.xml
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<title>UiGrid</title>
</head>
<body>
<referenceBlock name="menu">
<action method="setActive">
<argument name="itemId" xsi:type="string">Test_UiGrid::test_uigrid</argument>
</action>
</referenceBlock>
<referenceContainer name="content">
<uiComponent name="uigrid_grid_listing"/>
</referenceContainer>
</body>
</page>
di.xml — содержит информацию о data source collection для вашего Ui Component.
di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
<arguments>
<argument name="collections" xsi:type="array">
<item name="uigrid_grid_listing_data_source" xsi:type="string">Test\UiGrid\Model\ResourceModel\Grid\Grid\Collection</item>
</argument>
</arguments>
</type>
</config>
Эта информация будет использована Magento для того, чтобы подготовить данные для вашей Grid страницы. Проще говоря, указанный в di.xml класс — это просто коллекция с несколькими дополнительными методами для работы с search criteria и так далее. Давайте посмотрим на этот класс по ближе.
{NameSpace}/{ExtensionName}/Model/ResourceModel/{Entity}/Grid/Collection.php
namespace Test\UiGrid\Model\ResourceModel\Grid\Grid;
use Test\UiGrid\Model\ResourceModel\Grid\Collection as GridCollection;
use Magento\Framework\Search\AggregationInterface;
use Magento\Framework\Api\Search\SearchResultInterface;
use Magento\Framework\View\Element\UiComponent\DataProvider\Document;
use Test\UiGrid\Model\ResourceModel\Grid;
use Magento\Framework\Api\SearchCriteriaInterface;
class Collection extends GridCollection implements SearchResultInterface
{
protected $aggregations;
protected function _construct()
{
$this->_init(Document::class, Grid::class);
}
public function getAggregations()
{
return $this->aggregations;
}
public function setAggregations($aggregations)
{
$this->aggregations = $aggregations;
}
public function getAllIds($limit = null, $offset = null)
{
return $this->getConnection()->fetchCol($this->_getAllIdsSelect($limit, $offset), $this->_bindParams);
}
public function getSearchCriteria()
{
return null;
}
public function setSearchCriteria(SearchCriteriaInterface $searchCriteria = null)
{
return $this;
}
public function getTotalCount()
{
return $this->getSize();
}
public function setTotalCount($totalCount)
{
return $this;
}
public function setItems(array $items = null)
{
return $this;
}
}
Обратите внимание, что коллекция должна имплементить Magento\Framework\Api\Search\SearchResultInterface интерфейс и расширять вашу оригинальную коллекцию (на самом деле это делает работу с данными проще и вам не придется внедрять множество других методов). Все методы и свойства за исключением _construct могут быть скопированы из Magento\Cms\Model\ResourceModel\Block\Grid\Collection, больше они вам не понадобятся. Метод _construct особенный. Вы должны сделать так, чтобы коллекция использовала Magento\Framework\View\Element\UiComponent\DataProvider\Document объект как модель и вашу ресурс модель как, собственно, ресурс модель для общения с БД.
Ui Component
Ui Component — это ui_component/{entity_grid_listing}.xml файл, который предоставляет информацию о grid таблице и о том как данные должны быть в ней представлены.
С начала вам следует посмотреть module-cms/view/adminhtml/ui_component/cms_block_listing.xml файл, он выглядит относительно простым, но отсутствие описания в документации делает свое дело. Большинство ui grid страниц имеют схожую структуру такого файла: argument, dataSource, listingToolbar, columns.
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<argument name="data" xsi:type="array">
...
</argument>
<dataSource name="uigrid_grid_listing_data_source">
...
</dataSource>
<listingToolbar name="listing_top">
...
</listingToolbar>
<columns name="uigrid_grid_columns">
...
</columns>
</listing>
Но что они на самом деле делают? Важен ли порядок элементов? Какие параметры можно и нужно передавать? И самый главный, как же все это работает?
Ui Component – это новая особенность Magento 2, это смесь knockoutjs и бекенд кода. Когда вы используете uiComponent тег в вашем лаяуте это говорит Magento что надо обработать файл с таким то именем определенным способом. Вкратце, Magento читает компонент файл, создает определенные классы, для того, чтобы собрать опции для компонента и в конечном итоге подготавливает jsLayout конфиг, который будет передан на фронтенд и обработан knockoutjs (будут созданы observables, viewModels, создан мапинг view теплейтов и так далее). Magento_Ui – это тот экстеншен, который предоставляет большинство готовых к использованию компонентов (viewModels), которые вы можете использовать в своем коде. Вы можете найти их в module-ui/view/base/web/js/*. Главный же конфиг – это module-ui/view/base/ui_component/etc/definition.xml, он содержит описание и дефолтные опции для всех компонентов, которые вы можете использовать в вашем Ui Component. Любые изменения в этом файле (или вашем definition.xml файле) будут применены ко всем экстеншенам.
Ui Component конфиг
Разберем Test/UiGrid/view/adminhtml/ui_component/uigrid_grid_listing.xml. Для того, чтобы было проще проследить структуру я буду нумеровать вложенные элементы и выделять основные места.
Начнем с самого первого элемента, который мы видим в примере выше.
1. <argument name="data" xsi:type="array">.
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">uigrid_grid_listing.uigrid_grid_listing_data_source</item>
<item name="deps" xsi:type="string">uigrid_grid_listing.uigrid_grid_listing_data_source</item>
</item>
<item name="spinner" xsi:type="string">uigrid_grid_columns</item>
<item name="buttons" xsi:type="array">
<item name="add" xsi:type="array">
<item name="name" xsi:type="string">add</item>
<item name="label" xsi:type="string" translate="true">Add New Entity</item>
<item name="class" xsi:type="string">primary</item>
<item name="url" xsi:type="string">*/*/new</item>
</item>
<!--
<item name="back" xsi:type="string">Magento\Cms\Block\Adminhtml\Block\Edit\BackButton</item>
<item name="delete" xsi:type="string">Magento\Cms\Block\Adminhtml\Block\Edit\DeleteButton</item>
<item name="reset" xsi:type="string">Magento\Cms\Block\Adminhtml\Block\Edit\ResetButton</item>
<item name="save" xsi:type="string">Magento\Cms\Block\Adminhtml\Block\Edit\SaveButton</item>
<item name="save_and_continue" xsi:type="string">Magento\Cms\Block\Adminhtml\Block\Edit\SaveAndContinueButton</item>
-->
</item>
</argument>
<dataSource name="uigrid_grid_listing_data_source">
...
</dataSource>
<listingToolbar name="listing_top">
...
</listingToolbar>
<columns name="uigrid_grid_columns">
...
</columns>
</listing>
<item name="js_config" xsi:type="array"> содержит информацию о data provider на фронтенде, формат имени провайдера должен быть {file_name}.{file_name}_data_source.
<item name="spinner" xsi:type="string"> содержит ссылку на список столбцов в этом же файле, значение должно быть идентично имени, которое вы указали для тега columns. Я рекомендую называть его {extension}_{entity}_columns. Если вы не установили его или установили его не верно, то Magento не остановит spinner даже если данные уже загрузились.
<item name="buttons" xsi:type="array"> содержит информацию о верхних кнопках.
Обратите внимание, что вы можете не только добавить кнопку «Add …», но и другие кнопки с различными классами, как показано ниже.
Кнопка может быть добавлена не только через xml, но и через отдельный класс. Обратите внимание на закомментированный кусок кода. Реализацию этих классов вы найдете внутри них самих.
2. <dataSource name="uigrid_grid_listing_data_source">
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<argument name="data" xsi:type="array">
...
</argument>
<dataSource name="uigrid_grid_listing_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">uigrid_grid_listing_data_source</argument>
<argument name="primaryFieldName" xsi:type="string">entity_id</argument>
<argument name="requestFieldName" xsi:type="string">entity_id</argument>
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
<item name="update_url" xsi:type="url" path="mui/index/render"/>
<item name="storageConfig" xsi:type="array">
<item name="indexField" xsi:type="string">entity_id</item>
</item>
</item>
</argument>
</argument>
</dataSource>
<listingToolbar name="listing_top">
...
</listingToolbar>
<columns name="uigrid_grid_columns">
...
</columns>
</listing>
Эта секция содержит важную информацию о render url, data provider классе, имени вашей коллекции, которая предоставляет данные и так далее. Имя атрибута должно следовать следующему формату {file_name}_data_source и должно быть идентично тому, которое вы использовали ранее.
Вам необходимо изменить только следующие элементы:
<argument name="name" xsi:type="string"> должен содержать имя вашей коллекции в di.xml,
<argument name="primaryFieldName" xsi:type="string">, <argument name="requestFieldName" xsi:type="string">, <item name="indexField" xsi:type="string"> – entity id ключ вашей таблицы в БД.
Остальные атрибуты могут оставаться такими же как в примере.
Если имя задано не верно или коллекция не была описана в di.xml вы увидите следующую ошибку
3. <listingToolbar name="listing_top">
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<argument name="data" xsi:type="array">
...
</argument>
<dataSource name="uigrid_grid_listing_data_source">
...
</dataSource>
<listingToolbar name="listing_top">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="sticky" xsi:type="boolean">true</item>
</item>
</argument>
<bookmark name="bookmarks"/>
<columnsControls name="columns_controls"/>
<filterSearch name="fulltext"/>
<filters name="listing_filters">
...
</filters>
<massaction name="listing_massaction">
...
</massaction>
<paging name="listing_paging"/>
<exportButton name="export_button"/>
</listingToolbar>
<columns name="uigrid_grid_columns">
...
</columns>
</listing>
Этот элемент содержит список элементов верхнего меню, таких как Filters, Bookmarks, Column editor, Full text search field, Mass Actions, Pagination и так далее.
Имейте в виду, что вы можете заполнять эту xml в нескольких экстеншенах одновременно! Просто поместите ui_component файл с тем же именем в тот же или base scope. Порядок элемент играет большую разницу, поэтому следите за тем в каком порядке загружаются модули и элементы добавляются в ui_component. Если <listingToolbar> будет загружен после <columns>, вы получите следующий результат:
Имя элемента должно быть как указано примере.
<listingToolbar name="listing_top">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="sticky" xsi:type="boolean">true</item>
</item>
</argument>
...
</listingToolbar>
3.1. <item name="sticky" xsi:type="boolean"> опциональный, вы можете пропустить его. Значение по умолчанию «false». Этот параметр отвечает за быстрый доступ к топ меню во время прокрутки страницы, оно будет следовать за скролом, пока вы не прокрутите страницу обратно к самому верху.
3.2. <bookmark name="bookmarks"> опциональный. Он добавляет кнопку «Bookmark». Если вы добавите этот элемент, Magento позволит администраторам сохранять состояние столбцов и их позиции для использования позже. У каждого администратора свой собственный список.
3.3. <columnsControls name="columns_controls"> опциональный. Он добавляет кнопку «Columns». Если вы добавите этот элемент, Magento позволит администраторам добавлять или удалять некоторые столбцы из вашей grid таблицы.
3.4. <filterSearch name="fulltext"> опциональный. Добавляет full text search поле.
Magento разработчики внедрили замечательную фичу — поиск по любому полю в БД без написания дополнительного кода! Все что вам нужно сделать, это добавить full text index по 1 или нескольким столбцам в БД. Если у вашей таблицы есть хоть 1 full text index то введенный текст будет искаться по нему. Вы можете добавлять индексы в ваших инстал скриптах. Начиная с MySQL 5.6.4 InnoDB таблицы поддерживают Full text Index так же как и MyISAM.
3.5. <filters name="listing_filters"> опционален. Этот элемент может содержать дополнительные микронастройки для фильтров и их отображения. В примере вы можете видеть <argument> и <filterSelect> элементы.
<listingToolbar name="listing_top">
...
<filters name="listing_filters">
<!-- If you need to apply custom filter render you can use these tag -->
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="templates" xsi:type="array">
<item name="filters" xsi:type="array">
<item name="select" xsi:type="array">
<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>
</item>
</item>
</item>
</argument>
<!-- custom filter, Expected is one of ( filterInput, filterRange, filterSelect, containerConfiguration ) -->
<filterSelect name="store_id">
<argument name="optionsProvider" xsi:type="configurableObject">
<argument name="class" xsi:type="string">Magento\Cms\Ui\Component\Listing\Column\Cms\Options</argument>
</argument>
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="provider" xsi:type="string">${ $.parentName }</item>
<!-- data that will be sent to server -->
<item name="dataScope" xsi:type="string">store_id</item>
<item name="label" xsi:type="string" translate="true">Store View</item>
<!-- default value -->
<item name="captionValue" xsi:type="string">0</item>
</item>
</argument>
</filterSelect>
</filters>
...
</listingToolbar>
Давайте начнем с первого.
<argument>
Иногда вам может понадобиться изменить компонента или шаблон для определенного типа фильтра (например изменить поведение text input внутри списка фильтров или select элемент). Наиболее частый случай в Magento 2 коде это замена стандартного компонента и шаблона select дропдауна с select на ui-select для status фильтра.
Обратите внимание, что это изменение затронет все фильтры <item name={type}> типа.
<filterSelect>
Элемент «filterSelect» — это пример изменения стандартного фильтра для store_id колонки. В общем практически все столбцы имеют свой собственный фильтр (text, textRange, date, select и т.д.), но в некоторых случаях вам необходимо переопределить поведение/отображение такого фильтра для некой колонки. Доступные типы: filterInput, filterRange, filterSelect и containerConfiguration (об этом типе нам говорит сообщение в ошибке, если вы попробуете указать что-то другое). Имя должно быть идентично имени столбца, фильтр, которого вы хотите переопределить, в противном случае мапинг не будет работать.
3.6. <massaction name="listing_massaction"> элемент опционален. Он добавляет massaction дропдаун и всплывающее сообщения если пользователь не выбрал никакие строки до выбора действия.
Обычно этот элемент выглядит как обычный дропдаун, но вы можете заменить компонент на древообразное меню.
Если вы хотите заменить дефолтное сообщение «You haven’t selected any items!» как показано выше, вам надо передать следующие параметры в massaction component, просто вставьте свое сообщение в «noItemsMsg».
<massaction name="listing_massaction">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="noItemsMsg" xsi:type="string">Type here any text</item>
</item>
</argument>
...
</massaction>
Для того, чтобы добавить новое действие в дропдаун, взгляните на пример ниже. Это пример действия «delete», но вы можете добавить так же другие.
<massaction name="listing_massaction">
...
<action name="delete">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="type" xsi:type="string">delete</item>
<item name="label" xsi:type="string" translate="true">Delete</item>
<item name="url" xsi:type="url" path="uigrid/index/massDelete"/>
<item name="confirm" xsi:type="array">
<item name="title" xsi:type="string" translate="true">Delete items</item>
<item name="message" xsi:type="string" translate="true">Are you sure you want to delete selected items?</item>
</item>
</item>
</argument>
</action>
...
</massaction>
<action name="delete"> — должен иметь уникальное имя, так как Magento мерджит элементы по имени.
<item name="type"> — должен быть уникальным так же, в противном случае Magento будет показывать все такие опции в дропдауне, но все они будут выполнять 1 и тоже действие как было описано в 1ом элементе с этим типом так как Magento кеширует конфиги по типу. Хорошей практикой считается использование того же имени, что вы указали для экшена.
<item name="label"> — имя опции.
<item name="url"> — урл действия, который будет использован для обработки выбранных строк. Туда будет отправлен массив selected/excluded элементов, примененные фильтры и примененная full text search фраза. Разница между передаваемыми параметрами зависит от метода выбора элементов. Если вы нажали «select all» то элемент «excluded» будет содержать «false». Если вы выбрали несколько несколько элементов вручную, массив «selected» будет содержать entity id всех выбранных записей. Самый последний случай, если вы нажали «select all», но позже анчекнули несколько записей вручную, массив «excluded» будет содержать entity id всех анчекнутых записей. Чтобы посмотреть пример реализации «massDelete» экшена и как эти параметры обрабатываются посмотрите класс Magento\Cms\Controller\Adminhtml\Block\massDelete.
<item name="confirm"> — опциональный элемент. Если указан, Magento будет показывать модальное окно для подтверждения действия с «Ok» или «Cancel» кнопками. Title и Message могут быть изменены как показано выше.
Сейчас давайте рассмотрим не обычную кнопку, а mass edit кнопку.
<massaction name="listing_massaction">
...
<action name="edit">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="type" xsi:type="string">edit</item>
<item name="label" xsi:type="string" translate="true">Edit</item>
<item name="callback" xsi:type="array">
<item name="provider" xsi:type="string">uigrid_grid_listing.uigrid_grid_listing.uigrid_grid_columns_editor</item>
<item name="target" xsi:type="string">editSelected</item>
</item>
</item>
</argument>
</action>
</massaction>
Основная разница между ними это <item name="callback"> элемент. Он опционален. Его параметры делают возможным редактирование нескольких строк сразу. По факту, он применяет колбек к выбранным строкам.
Вот так изменяется грид если выбрано несколько строк:
и если выбрана только 1 стока:
Для подобного редактирования будут доступны только те колонки, которые имеют «editor» атрибут (больше информации о нем ниже).
<item name="provider"> — это путь до компонента. Обратите внимание на строку в примере. Значение должно следовать следующему формату {filename}.{filename}.{ columns_element_name}_editor.
<item name="target"> — это имя метода внутри knockoutjs компонента, «editSelected» должен быть указан тут.
Детальная конфигурация редактора будет рассмотрена чуть позже.
Говоря об опциях massaction дропдауна, как вы видели раньше, там доступно 2 типа опций. Обычные (select) и древоподобные опции. К несчастью «select» компонент не поддерживает подменю, но tree-massactions поддерживает. Для применения этого компонента вам надо сказать Magento использовать Magento_Ui/js/grid/tree-massactions компонент. «Action» элемент должен быть уже знаком вам, поэтому давайте взглянем на минорные изменения в следующем примере.
<massaction name="listing_massaction">
...
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/tree-massactions</item>
</item>
</argument>
<action name="status">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="type" xsi:type="string">status</item>
<item name="label" xsi:type="string" translate="true">Change status</item>
</item>
</argument>
<argument name="actions" xsi:type="array">
<item name="0" xsi:type="array">
<item name="type" xsi:type="string">enable</item>
<item name="label" xsi:type="string" translate="true">Enable</item>
<item name="url" xsi:type="url" path="uigird/index/massStatus">
<param name="status">1</param>
</item>
</item>
<item name="1" xsi:type="array">
<item name="type" xsi:type="string">disable</item>
<item name="label" xsi:type="string" translate="true">Disable</item>
<item name="url" xsi:type="url" path="uigrid/index/massStatus">
<param name="status">2</param>
</item>
</item>
</argument>
</action>
...
</massaction>
<argument name="actions" xsi:type="array"> опционален. Он содержит массив элементов с именами от 0 до N, если имена не будут следовать целочисленной последовательности то knockoutjs (javascript) выбросит ошибку.
<param name="…">…</param> так же опционален. Пока вся информация о выбранных строках будет передана в теле post запроса, эти параметры будут переданы как get параметры и зависят только от выбранной опции (см. пример выше). Эти параметры могут быть использованы и с другими масс экшенами.
3.7. <paging name="listing_paging"/> опциональный элемент. Он добавляет пагинацию для вашей грид страницы. Если он не был добавлен, Magento будет показывать все записи на 1 станице и не будет показывать количество найденных записей.
С элементом:
без элемента:
3.8. <exportButton name="export_button"/> опциональный элемент. Этот компонент добавляет кнопку export с 2мя опциями: export as csv, export as xml. Вам не надо имплементить дополнительную логики, чтобы эта фича работала. Она генерирует фид файл содержащий только доступные данные, согласно примененным фильтрам. Файл игнорирует сорт ордер и видимость элементов на экране, Magento всегда генерирует файл включающий все колонки из ui_component файла. Колонки будут в порядке их появление в этом файле, полностью игнорируя иную сортировку (включая атрибут сортировки элементов в файле). Вы так же можете добавить другие форматы для экспорта, как это сделать описано в документации devdocs.magento.com/guides/v2.1/ui-components/ui-export.html.
4. <columns name="uigrid_grid_columns">
...
<columns name="uigrid_grid_columns">
<argument name="data" xsi:type="array">
...
</argument>
<selectionsColumn name="ids">
...
</selectionsColumn>
<column name="entity_id">
...
</column>
<actionsColumn name="actions" class="Test\UiGrid\Ui\Component\Listing\Column\Action"/>
</columns>
Это наиболее интересная и важная часть для отображения колонок в гриде. Этот элемент содержит список столбцов, которые должны быть доступны админу.
<columns name="uigrid_grid_columns"> — имя элемента должно быть следующего формата {extension}_{entity}_columns и быть идентично тому, что вы прописали в <item name="spinner" xsi:type="string">name_of_columns_element</item>. Обычно этот тег имеет только атрибут «name», но может так же иметь и «class» как в vendor/magento/module-catalog/view/adminhtml/ui_component/product_listing.xml.
<columns name="product_columns" class="Magento\Catalog\Ui\Component\Listing\Columns">
Вам нужно использовать класс в элементе columns только если вы хотите обрабатывать какие-то данные динамически вроде сортировки, видимости каких-то колонок или же добавлять новые столбцы динамически.
Editor
...
<columns name="uigrid_grid_columns">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="editorConfig" xsi:type="array">
<item name="selectProvider" xsi:type="string">uigrid_grid_listing.uigrid_grid_listing.uigrid_grid_columns.ids</item>
<item name="enabled" xsi:type="boolean">true</item>
<item name="indexField" xsi:type="string">entity_id</item>
<item name="clientConfig" xsi:type="array">
<item name="saveUrl" xsi:type="url" path="*/*/inlineEdit"/>
<item name="validateBeforeSave" xsi:type="boolean">false</item>
<!--
<item name="validateBeforeSave" xsi:type="boolean">true</item>
<item name="validateUrl" xsi:type="url" path="*/*/checkData"/>
-->
</item>
</item>
</item>
</argument>
...
</columns>
Если вы хотите добавить «edit» массэкшен в список массэкшенов или сделать доступным инлайн редактор вам необходимо сперва его сконфигурировать.
<item name="selectProvider" xsi:type="string"> — путь к колонке/компоненту в дереве, придерживайтесь следующего формата:
{filename}.{filename}.{columns_name}.{selectionsColumn_name},
в примере это uigrid_grid_listing.uigrid_grid_listing.uigrid_grid_columns.ids.
<item name="enabled" xsi:type="boolean"> — включить/выключить редактор.
<item name="indexField" xsi:type="string"> — entity id, будет использоваться при сохранении данных.
<item name="clientConfig" xsi:type="array"> — конфигурация «Save» экшена.
<item name="saveUrl" xsi:type="url" path="*/*/inlineEdit"/> — урл, который knockoutjs использует для сохранения инлайн изменений. Обратите внимание на «path», я специально указал урл как "*/*/inlineEditor", чтобы показать, что такие урлы так же поддерживаются.
<item name="validateBeforeSave" xsi:type="boolean"> — это весьма интересная опция. Дефолтное значение – «true», так что если вы пропустили эту настройку и не указали следующий параметр «validateUrl», knockoutjs выбросит ошибку. Если эта настройка включена, knockoutjs отправляет новые значения на «validateUrl» и если респонс в порядке (например http код 200), knockoutjs отправит эти же данные на saveUrl, в противном случае покажет сообщение с ошибкой. Если вам не нужен этот функционал и вы просто хотите сохранять данные и возможно валидировать их прямо там то установите параметр «false».
<item name="validateUrl" xsi:type="url" path="*/*/checkData"/> — урл для валидации данных.
Настройка InlineEditor
Если вы хотите активировать инлайн редактор по клику на строчку (например как на CMS page/block гридах), вам необходимо добавить конфиг в <argument> вашего <columns> тега сразу после «editorConfig». Единственный параметр, который вам надо поменять это «provider», он должен следовать следующему формату {filename}.{filename}.{columns_name}_editor, все остальные параметры должны быть как в примере ниже.
...
<columns name="uigrid_grid_columns">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="editorConfig" xsi:type="array">
...
</item>
<item name="childDefaults" xsi:type="array">
<item name="fieldAction" xsi:type="array">
<item name="provider" xsi:type="string">uigrid_grid_listing.uigrid_grid_listing.uigrid_grid_columns_editor</item>
<item name="target" xsi:type="string">startEdit</item>
<item name="params" xsi:type="array">
<item name="0" xsi:type="string">${ $.$data.rowIndex }</item>
<item name="1" xsi:type="boolean">true</item>
</item>
</item>
</item>
</item>
</argument>
...
</columns>
По определенным причинам инлайн редактор может не подойти вам. В таком случае вы можете захотеть выполнять другие действия по клику на строчку. Для этого, поместите следующий код вместо вызова inlineEditor. Вам необходимо изменить только 2 параметра там: provider,0. Провайдер должен следовать следующему формату {filename}.{filename}.{columns_name}.actions, имя экшена из вашего «action» списка (см. ниже).
...
<columns name="uigrid_grid_columns">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
...
<item name="childDefaults" xsi:type="array">
<item name="fieldAction" xsi:type="array">
<item name="provider" xsi:type="string">uigrid_grid_listing.uigrid_grid_listing.uigrid_grid_columns.actions</item>
<item name="target" xsi:type="string">applyAction</item>
<item name="params" xsi:type="array">
<!-- name of action from action class -->
<item name="0" xsi:type="string">view</item>
<item name="1" xsi:type="string">${ $.$data.rowIndex }</item>
</item>
</item>
</item>
</item>
</argument>
...
</columns>
Columns
<column|actionsColumn|selectionsColumn name="{unique_name}" class="{class_name}">
<argument name="data" xsi:type="array">
<item name="options" xsi:type="object">{source_model_class}</item>
<item name="config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/{date|select|thumbnail|column|*}</item>
<item name="bodyTmpl" xsi:type="string">ui/grid/cells/{html|text|*}</item>
<item name="add_field" xsi:type="boolean">{true|false}</item>
<item name="sortable" xsi:type="boolean">{true|false}</item>
<item name="filter" xsi:type="string">{textRange|dateRange|select|text}</item>
<item name="sorting" xsi:type="string">{asc|desc}</item>
<item name="label" xsi:type="string" translate="true">{label}</item>
<item name="visible" xsi:type="boolean">{true|false}</item>
<item name="draggable" xsi:type="boolean">{true|false}</item>
<!-- <item name="editor" xsi:type="string">{text|date|select}</item> -->
<item name="editor" xsi:type="array">
<item name="editorType" xsi:type="string">{text|date|select}</item>
<item name="options" xsi:type="array">
<item name="showsTime" xsi:type="boolean">{true|false}</item>
</item>
<item name="validation" xsi:type="string">{validation_rule}</item>
<!--
<item name="validation" xsi:type="array">
<item name="validate-xml-identifier" xsi:type="boolean">true</item>
<item name="required-entry" xsi:type="boolean">true</item>
</item>
-->
</item>
<item name="timezone" xsi:type="boolean">{true|false}</item>
<item name="dataType" xsi:type="string">{dataType}</item>
<item name="sortOrder" xsi:type="number">{position}</item>
<item name="options" xsi:type="array">
<item name="0" xsi:type="array">
<item name="value" xsi:type="string">{value}</item>
<item name="label" xsi:type="string">{option_label}</item>
</item>
<item name="1" xsi:type="array">
<item name="value" xsi:type="string">{value}</item>
<item name="label" xsi:type="string">{option_label}</item>
</item>
</item>
<item name="has_preview" xsi:type="boolean">{true|false}</item>
</item>
</argument>
</column|actionsColumn|selectionsColumn>
<column|actionsColumn|selectionsColumn> — все эти элементы расположены внутри <columns> тега, они имеют схожий синтаксис. <column> используется для добавления обычной колонки, <actionsColumn> используется для добавления столбца «action» и наконец <selectionsColumn> используется для добавления колонки с чекбоксами для выбора строк. <actionsColumn> может быть пропущен если вы хотите использовать только инлайн редактор. Имя selectionsColumn атрибута должно быть ids, он не имеет атрибута class и может быть пропущен если вы не хотите использовать экспорт, инлайн редактор, масс экшены и т.д.
<column name="{unique_name}"> — это обязательный атрибут. Это уникальное имя столбца. Magento перезаписывает столбцы по имени. Имя столбца может быть не идентично имени колонки в БД (ключу в вашей коллекции), это лишь имя колонки. Если же имя колонки идентично имени колонки в БД, Magento замапит данные из коллекции в это поле автоматически и эти данные будут доступны (видимы) в гриде. В противном случае необходимо использовать атрибут «class», чтобы получить/подготовить необходимое значение.
<column class="{class_name}"> — это опциональный атрибут. Главная особенность «класса» это форматирование/подготовка данных из коллекции для отображения в колонке/использования компонентом. Класс имеет доступ к данным коллекции для этой строки и может модифицировать любое значение как и добавлять/удалять некоторые ключи. Класс Magento\Ui\Component\Listing\Columns\Date форматирует дату из БД, приводит ее к необходимому формату и так же применяет сдвиг для тайм зоны. Класс Magento\Catalog\Ui\Component\Listing\Columns\Thumbnail предоставляет данные для тамбнейл компонента. Посмотрите их код, чтобы лучше понять как они работают.
<argument name="data" xsi:type="array"> — это обязательный тег если вы хотите предоставить дополнительные данные в класс вашего столбца (будут доступны все данные внутри тега) или в его компонент (будут доступны все данные внутри внутреннего «config» тега).
<item name="options" xsi:type="object"> — опциональный элемент. Нативно используется только с dataType «select» (см. дальше) для отображения опций из source модельки, но вы можете использовать этот параметр для обработки данных в вашем классе (они имеют полный доступ ко всем данным внутри «data» тега, но эти данные не будут доступны в knockoutjs компоненте). Так же есть и другие способы сделать тоже самое, см. ниже.
<item name="config" xsi:type="array"> — обязателен если вам нужно передать какие-либо данные в компонент класс и/или knockoutjs компонент. Вы можете иметь полный доступ к этим данным внутри вашей knockoutjs ViewModel. По умолчанию, ViewModel не имеет доступа к параметрам за пределами «config» тега.
<item name="component" xsi:type="string"> — опциональный. Проще говоря, компоненты рендерят значения для отображения в колонках. На пример, один из них отвечает за отображение «Sep 5, 2016 8:03:07 PM» вместо 2016-09-05 в колонке даты. Значение по умолчанию – это Magento_Ui/js/grid/columns/column, он же дефолтный компонент для всех колонок. ViewModel’и для рендеринга колонок расположены в Magento_Ui/js/grid/columns/. Наиболее используемые значения (компоненты) в этом теге:
Magento_Ui/js/grid/columns/column – отображает значение как текстовое, т.е. как есть,
Magento_Ui/js/grid/columns/date – отображает даты согласно указанному формату,
Magento_Ui/js/grid/columns/select – отображает значения как выбранные селект опции с мапингом значений и их лейблов,
Magento_Ui/js/grid/columns/thumbnail – показывает изображение в колонке,
Вы так же можете создать свои собственные компоненты, просто «наследуйтесь» от Magento_Ui/js/grid/columns/column.
<item name="bodyTmpl" xsi:type="string"> — опциональный. Вы можете изменить шаблон («view») для значения, который будет использоваться в столбце. Дефолтное значение ui/grid/cells/text. Если данные не могут быть трансформированы в текст и вам нужно больше возможностей для использования html внутри, используйте шаблон ui/grid/cells/html (он обычно используется в Store Id колонках) или любой подходящий из ui/grid/cells (или вашего экстеншена).
<item name="add_field" xsi:type="boolean"> — опциональный. Вы могли видеть этот тег в некоторых ui_*.xml файлах, он требует дополнительной реализации в DataProvider/collection классах и обязателен для eav/значений из отдельных таблиц только так как такие столбцы могут быть не найдены в основной таблице без этого вызова.
<item name="sortable" xsi:type="boolean"> — опциональный. Дефолтное значение «true». Он отключает способность применять сортировку по клику на столбце.
<item name="filter" xsi:type="string"> — опциональный. Этот параметр добавляет фильтр к колонке. Он поддерживает следующие значения: textRange, dateRange, select, text. Обратите внимание на скриншот ниже. (ID – textRange, Created – dateRange, Store View – кастомный фильтр, Name – text, Status – select).
Если вам надо использовать кастомный фильтр для колонки (например селект с группами, основанный на кастомной модельке, вроде списка Website/StoreView) вы можете пропустить фильтр параметр в списке параметров вашей колонки и добавить описание фильтра в <filters name="listing_filters">.
<item name="sorting" xsi:type="string"> — опционанальный, он применяет сортировку ко всему гриду по этому полю. Доступные следующие опции: asc, desc. Только к 1 полю может быть применена сортировка по умолчанию.
<item name="label" xsi:type="string"> — обязательное. Вкратце, это имя вашей колонки, оно будет отображаться в хедере вашей колонки. По факту, это просто текст и используется «ui/grid/columns/text» шаблон, который указан в «headerTmpl» параметре. Вы можете изменить его, если вам надо.
<item name="visible" xsi:type="boolean"> — опциональный. Дефолтное значение «true». Этот параметр позволяет скрыть колонку из грида, но она будет доступна в списке доступных колонок, ее можно будет добавить оттуда.
<item name="draggable" xsi:type="boolean"> — опциональный. Дефолтное значение «true». Делает столбец статичным/не перемещаемым.
<item name="editor" xsi:type="{string|array}"> — опциональный. Позволяет использовать инлайн едитор для колонки. Если тег пропущен то значение в этом столбце нельзя будет редактировать при вызове инлайн едитора по клику на строке или через масс экшен меню. Есть 2 способа применения этого тега. Он может иметь тип «string» или тип «array». Если вам надо включить едитор для этого поля то используйте «string» и укажите тип (режим) для этого поля, но если вы хотите сконфигурировать едитор более точно то используйте тип «array». Всего есть 3 режима: text, date, select. Вы должны выбрать 1 из них.
Список настроек для едитора:
- <item name="editorType" xsi:type="string"> — тип едитора. Возможны такие же значения как и в «string» версии: text, date, select.
- <item name="showsTime" xsi:type="boolean"> — опциональный. Используется только с «date» типом. Позволяет модифицировать не только дату, но и время. Дефолтное значение «false».
- <item name="validation" xsi:type="{string|array}"> — опциональный. Может быть либо «string» либо «array». Примеряет валидацию к полю редактирования. Все возможные варианты валидаций вы можете посмотреть в vendor\magento\magento2-base\lib\web\mage\validation.js. Если вам надо применить больше чем 1 валидацию то вам надо использовать тип «array» и указать необходимые правила валидации в следующем формате:
- <item name="{validation_rule}" xsi:type="boolean">true</item>
<item name="timezone" xsi:type="boolean"> — опциональный. Дефолтное значение «true». Эта опция применима только к колонкам типа «date». Она используется в Magento\Ui\Component\Listing\Columns\Date классе. Позволяет скорректировать тайм зону если в БД и в админ панели у вас используют разные тайм зоны.
<item name="dataType" xsi:type="string"> — опциональный. В реальной жизни, полезен только со столбцами типа «select». Дефолтное значение «text». Доступные значения любые сущности(теги) из /vendor/magento/module-ui/view/base/ui_component/etc/definition.xml. Что такое dataType? Проще говоря, это дефолтное поведение ваших элементов. Когда Magento начинает обрабатывать конфиг вашего столбца, она читает dataType параметр, загружает его описание из definition.xml, запускает объект класса, который указан для этого dataType («class» аттрибут). Этот объект имеет полный доступ к параметрам, переданным в «data» тег и может модифицировать их. После обработки этих данных Magento мерджит конфиг из definition.xml, данными сгенерированные указанным объектом с вашим описанием колонки и передает эти данные на фронтенд, где knockoutjs начинает обрабатывать полученный конфиг. Относительно грида, единственный полезный dataType это «select» благодаря классу Magento\Ui\Component\Form\Element\Select, который связан с ним. Этот класс обрабатывает тег «options» и форматирует данные из указанной source model в подходящий массив опций, которые могут быть в дальнейшем обработаны Magento_Ui/js/grid/columns/select (нативный select компонент).
<item name="sortOrder" xsi:type="number"> — опциональный. Если sortOrder пропущен, Magento отображает столбцы в порядке их описания в ui_component файле. Если же этот параметр присутствует, то Magento отображает элементы согласно sortOrder параметру, но в экспорт файле порядок колонок будет идентичен порядку элементов в ui_component файле! Имейте в виду, что после первого раза, как админ откроет вашу грид страницу порядок элементов будет сохранен в БД и любые изменения sortOrder параметра не будут применены. Более того, новые колонки всегда будут добавлены в самый конец. Подробнее об этом вы найдете ниже.
<item name="options" xsi:type="array"> — опциональный и является альтернативным способом рендеринга колонки типа «select». Может быть использован с «select» компонентом. Ранее было сказано, что для отображения лейблов вместо ключей из БД вам надо использовать «option» тег с сорс моделькой и указать dataType=«select». Другой способ так же существует. «select» компоненту нужен массив опций для того, чтобы отобразить лейблы вместо id. Если в случае с сорс моделькой dataType элемент подготавливает значения, вы можете так сформировать необходимый массив опций вручную. Обратите внимание на синтаксис:
<item name="0" xsi:type="array">
<item name="value" xsi:type="string">{value}</item>
<item name="label" xsi:type="string">{option_label}</item>
</item>
<item name="1" xsi:type="array">
<item name="value" xsi:type="string">{value}</item>
<item name="label" xsi:type="string">{option_label}</item>
</item>
Каждый айтем это опция/маппинг. Вместо {value} будет отображено {option_label}. Это довольно удобный способ, но если у вас уже есть сорс моделька для вашего дропдауна использование dataType подхода более оправдано.
<item name="has_preview" xsi:type="boolean"> — опциональный. Применим только с «thumbnail» компонентом/столбцами. Дефолтное значение «false». Если он включен тогда по клику на изображении в гриде будет показано модальное окно с большим изображением и ссылкой на страницу редактирования.
Для того, чтобы посмотреть все доступные параметры и какие возможности есть у каждого из компонентов вы можете посмотреть их исходный код.
Examples
Minimum required data for creating a column
<column name="data">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="label" xsi:type="string" translate="true">Data</item>
</item>
</argument>
</column>
Этот столбец просто отображает данные с именем «data» из БД как есть. Он не имеет фильтра или инлайн редактора.
Selections column
Это довольно важный столбец. Он предоставляет не только «select all», «select all on this page», «deselect all», «deselect all on this page», чекбоксы, но и маппинг строк и их id. Практически всегда описывается первым.
<selectionsColumn name="ids">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="indexField" xsi:type="string">entity_id</item>
</item>
</argument>
</selectionsColumn>
<selectionsColumn name="ids"> имя должно быть «ids».
<item name="indexField" xsi:type="string"> имя primary key в БД.
Text column
<column name="name">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="editor" xsi:type="string">text</item>
<item name="filter" xsi:type="string">text</item>
<item name="label" xsi:type="string" translate="true">Name</item>
</item>
</argument>
</column>
Этот столбец показывает значения как есть из БД, но так же обладает простым текстовым фильтром и поддерживает инлайн редактор.
Date column
Есть 2 режима для отображения и инлайн редактора. Date и datetime.
<column name="date" class="Magento\Ui\Component\Listing\Columns\Date">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<!-- <item name="editor" xsi:type="string">date</item> -->
<item name="editor" xsi:type="array">
<item name="editorType" xsi:type="string">date</item>
<item name="options" xsi:type="array">
<item name="showsTime" xsi:type="boolean">true</item>
</item>
</item>
<item name="timezone" xsi:type="boolean">false</item>
<item name="filter" xsi:type="string">dateRange</item>
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item>
<item name="label" xsi:type="string" translate="true">Created</item>
<item name="dateFormat" xsi:type="string">MMM d</item>
</item>
</argument>
</column>
Класс Magento\Ui\Component\Listing\Columns\Date позволяет скорректировать тайм зону для данных из БД к выбранной локали.
Компонент Magento_Ui/js/grid/columns/date предоставляет необходимый функционал для отображения дат.
<item name="editor" xsi:type="array"> устанавливает инлайн редактор для поля.
<item name="showsTime" xsi:type="boolean"> — опциональный. Устанавливает режим. Дефолтное значение «false». Если вы хотите заставить Magento показывать селектор времени то установите значение в «true». Если вы хотите отображать корректную дату в инлайн редакторе вам необходимо установить showTime = true, в противном случае дата будет сбрасываться на сегодняшний день при запуске инлайн едитора – это баг Magento 2.
<item name="timezone" xsi:type="boolean"> — опциональный параметр. Дефолтное значение «true». Если вам надо отключить коррекцию времени укажите этот параметр и передайте «false», в противном случае она будет применена. Учтите, что время в инлайн редакторе будет отображаться с учетом тайм зоны (если не отключено) и когда вы нажмете на «save» на сервер отправится именно это время.
<item name="filter" xsi:type="string">dateRange</item> — опциональный. Добавляет фильтр в список фильтров. Имейте в виду, он не зависит от настроек редактора, дефолтный фильтр для DataRange отображает только даты.
<item name="dateFormat" xsi:type="string"> — опциональный. Позволяет указать формат для отображения даты в столбце. Дефолтное значение «MMM d, YYYY h:mm:ss A», что эквивалентно «Sep 5, 2016 9:00:00 AM».
Select column
Наиболее распространенный столбец типа «select» это Status. Обычно он имеет всего 2 значения Enabled и Disabled.
<column name="is_active">
<argument name="data" xsi:type="array">
<item name="options" xsi:type="object">Magento\Cms\Model\Block\Source\IsActive</item>
<item name="config" xsi:type="array">
<item name="dataType" xsi:type="string">select</item>
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item>
<item name="editor" xsi:type="string">select</item>
<item name="filter" xsi:type="string">select</item>
<item name="label" xsi:type="string" translate="true">Status</item>
</item>
</argument>
</column>
<item name="options" xsi:type="object"> — обязательное для подхода с использованием сорс модели. Предоставляет массив значений (через сорс модель), но knockoutjs компонент не может использовать эти данные на прямую.
<item name="dataType" xsi:type="string"> — обязательное для этого подхода. Использует класс из «options» и получает список всех доступных значений. Далее «select» класс форматирует полученный массив опций для knockoutjs компонента. После чего компонент рендерит эти данные как «select».
Если у вас нет сорс модели и вы не хотите создавать ее вы можете предоставить список необходимых значений непосредственно в xml.
<column name="is_active">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="options" xsi:type="array">
<item name="0" xsi:type="array">
<item name="value" xsi:type="string">0</item>
<item name="label" xsi:type="string">Disabled</item>
</item>
<item name="1" xsi:type="array">
<item name="value" xsi:type="string">1</item>
<item name="label" xsi:type="string">Enabled</item>
</item>
</item>
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item>
<item name="editor" xsi:type="string">select</item>
<item name="filter" xsi:type="string">select</item>
<item name="label" xsi:type="string" translate="true">Status</item>
</item>
</argument>
</column>
<item name="options" xsi:type="array"> — обязательное поле для подхода без использования сорс модели. Оно содержит массив ключ/значение.
Store View column
<column name="store_id" class="Magento\Store\Ui\Component\Listing\Column\Store">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>
<item name="label" xsi:type="string" translate="true">Store View</item>
</item>
</argument>
</column>
В большинстве случаев Store View хранится как store_id (идентификатор стора), но показывать это как есть не самая лучшая идея. Для того, чтобы заменить это значение на имя стора надо использовать кастомный класс. Чтобы показать данные как на скриншоте выше надо использовать html, так как дефолтный шаблон отображает только текстовые значения. Надо изменить его в «bodyTmpl». Класс Magento\Store\Ui\Component\Listing\Column\Store заменяет идентификатор на структурированное Website-Store-StoreView html значение. Имейте в виду, что после этого так же надо применить кастомный фильтр, чтобы позволить фильтровать эти данные в таком же виде.
Thumbnail column
<column name="image" class="Magento\Catalog\Ui\Component\Listing\Columns\Thumbnail">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/thumbnail</item>
<item name="has_preview" xsi:type="string">1</item>
<item name="label" xsi:type="string" translate="true">Image</item>
</item>
</argument>
</column>
Thumbnail столбцы немного специфичные в имплементации. Компонент требует следующие данные:
- {column_name}_src – урл маленького изображения,
- {column_name}_alt – alt текст,
- {column_name}_link – ссылка на страницу редактирования, которая используется во всплывающем окне,
- {column_name}_orig_src – урл оригинального изображения, которое оказывается во вплывающем окне.
*{column_name} это «image» в примере.
Эти данные редко хранятся в БД, для предоставления этих данных на странице продуктов используется Magento\Catalog\Ui\Component\Listing\Columns\Thumbnail. Посмотрите его исходный код, чтобы создать вашу собственную реализацию.
<item name="has_preview" xsi:type="boolean"> — опциональный. Включение этой опции позволяет показывать всплывающее окно по клику на изображении в столбце.
Action column
Столбец «Action» использует «actionColumn» тег вместо «column», но его особенности и синтаксис такие же. Столбец может быть создан 2мя способами.
Способ первый
Для создания такого «action» столбца используйте следующую короткую:
<actionsColumn name="actions" class="Test\UiGrid\Ui\Component\Listing\Column\Action"/>
или полную запись:
<actionsColumn name="actions" class="Test\UiGrid\Ui\Component\Listing\Column\Action">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="indexField" xsi:type="string">entity_id</item>
</item>
</argument>
</actionsColumn>
На деле, они идентичны. Единственная разница это «indexField» элемент. По факту, этот параметр не очень важен и не затрагивает функциональность, там нет жизненно необходимых мест в его knockoutjs компонент коде. Так что я просто пропустил его в короткой форме, но это может не работать в будущих обновлениях после рефакторинга кода этого компонента.
Главная часть это класс, он возвращает список опций. Для имплементации класса вроде этого посмотрите Magento\Cms\Ui\Component\Listing\Column\BlockActions.php.
Magento отображает дропдаун «Select» если есть хотя бы 1 опция.
Способ второй
Так же можно добавить «action» столбец без создания новых классов.
<actionsColumn name="actions" class="Magento\Sales\Ui\Component\Listing\Column\ViewAction">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="indexField" xsi:type="string">entity_id</item>
<item name="viewUrlPath" xsi:type="string">ugrid/enity/view</item>
<item name="urlEntityParamName" xsi:type="string">uigrid_id</item>
</item>
</argument>
</actionsColumn>
Вы можете использовать «Magento\Sales\Ui\Component\Listing\Column\ViewAction» класс. Он очень полезен для многих случаев. Вам всего-то надо иметь конфиг вроде того, что показан выше и primary key полем в БД должно быть «entity_id».
<item name="indexField" xsi:type="string"> — см. выше,
<item name="viewUrlPath" xsi:type="string"> — урл страницы редактирования,
<item name="urlEntityParamName" xsi:type="string"> — имя entity_id поля, которое будет отправляться на страницу редактирования в качестве GET параметра. Дефолтное значение «entity_id», так что оно может быть пропущено, но если вы хотите отправлять что-то отличное от entity_id то укажите его как показано в примере.
На самом деле параметры для компонента могут быть предоставлены полностью через xml, но в таком случае вам надо будет указывать полный урл до страницы редактирования записи, что менее удобно.
Необходимо помнить
Как только админ откроет грид страницу в первый раз Magento сохранит порядок столбцов, примененную сортировку данных, показанные элементы и так далее в ui_bookmark таблицу и последующие изменения в ui_component.xml не смогут изменить этого. Даже если вы в дальнейшем добавите новый столбец в начало файла или в середину, Magento будет отображать этот столбец в самом конце списка, даже если последний столбец был «actions» и он был отмечен как не перемещаемый, игнорируя sortOrder атрибут. Чтобы сбросить эти изменения вам понадобиться удалить все записи, которые имеют нейм спейс идентичный вашему гриду (имя файла) из БД (как минимум имеющие идентификатор «default», который применяется к новым пользователям, и «current» если вы хотите сбросить активные пользовательские изменения так же).
Заключение
Подводя итог, я хотел бы сказать, что ui компоненты имеют массу возможностей. Благодаря knockoutjs и его внедрению в ui компоненты, разработчики могут создавать динамический контент без добавления дополнительных библиотек и обновления страниц как это было в Magento 1. Единственный недостаток здесь это то, что разработчикам необходимо потратить определенное время для понимания идеи и подхода для того, чтобы начать работать с новой фичей эффективно. Сама Magento 2, как и ее документация, продолжает развиваться каждый день. Прежде всего обратите внимания на это. Это хорошая идея начать ваше погружение в ui компоненты с оффициальной документации. Вы можете найти больше информации о Ui Component по ссылке или тут.
Поделиться с друзьями