Atualizando a grade padrão do Magento 2 com componentes de interface do usuário (parte 2)
Publicados: 2016-10-18No artigo anterior, descrevemos como criar um módulo com as condições básicas e a interface que nos permitirá trabalhar com elas. Durante o processo de criação, usamos os blocos padrão do Magento. No entanto, o Magento 2 é capaz de fazer muito mais.
Estou falando da possibilidade de melhorar a interface com a ajuda de componentes de interface do usuário. Esses componentes são adicionados com o módulo Magento/UI.
*embora esses componentes possam ser encontrados na v.2.0, recomendamos fortemente que você use a versão 2.1.
Neste artigo, você aprenderá a refazer o Grid padrão (localizado no layout: app/code/Vendor/Rules/view/adminhtml/layout/vendor_rules_example_rule_index.xml ) e enriquecê-lo com componentes de interface do usuário.
Basta comparar. Esta é uma grade antiga:
com um novo, feito com componentes UX:
Como você pode ver, um Grid atualizado será muito mais fácil de usar e economizar tempo, mais fácil de dimensionar, tem muitos recursos extras excelentes (por exemplo, marcadores que são capazes de salvar o estado atual do Grid) e definir filtros inteligentes.
Então vamos começar.
Primeiro, você precisa fazer algumas alterações no módulo. Abaixo está como fazer isso:
1) Crie um novo arquivo para declarar os componentes necessários:
> app/code/Vendor/Rules/etc/di.xml
<?xml version="1.0"?> <config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <virtualType name="VendorRulesRuleGridDataProvider" type="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider"> <argumentos> <argument name="collection" xsi:type="object" shared="false">Fornecedor\Rules\Model\ResourceModel\Rule\Collection</argument> <argument name="filterPool" xsi:type="object" shared="false">VendorRulesRuleGridFilterPool</argument> </argumentos> </virtualType> <virtualType name="VendorRulesRuleGridFilterPool" type="Magento\Framework\View\Element\UiComponent\DataProvider\FilterPool"> <argumentos> <argument name="appliers" xsi:type="array"> <item name="regular" xsi:type="object">Magento\Framework\View\Element\UiComponent\DataProvider\RegularFilter</item> <item name="fulltext" xsi:type="object">Magento\Framework\View\Element\UiComponent\DataProvider\FulltextFilter</item> </argumento> </argumentos> </virtualType> <type name="Fornecedor\Rules\Model\ResourceModel\Rule\Grid\Collection"> <argumentos> <argument name="mainTable" xsi:type="string">vendor_rules</argument> <argument name="eventPrefix" xsi:type="string">vendor_rules_rule_grid_collection</argument> <argument name="eventObject" xsi:type="string">rule_grid_collection</argument> <argument name="resourceModel" xsi:type="string">Fornecedor\Rules\Model\ResourceModel\Rule</argument> </argumentos> </tipo> <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory"> <argumentos> <argument name="collections" xsi:type="array"> <item name="vendor_rules_rule_listing_data_source" xsi:type="string">Fornecedor\Rules\Model\ResourceModel\Rule\Grid\Collection</item> </argumento> </argumentos> </tipo> </config>
VendorRulesRuleGridDataProvide — esse tipo virtual fornece dados para a grade de regras da interface do usuário. VendorRulesRuleGridFilterPool , por sua vez, adiciona a funcionalidade de filtragem que permite adicionar/modificar quaisquer filtros existentes.
Observe que, para que o Grid funcione corretamente com essa coleção específica, você precisa adicioná-la à lista de todas as coleções disponíveis. Para fazer isso, adicione vendor_rules_rule_listing_data_source com a classe baseada em valor de coleção: Vendor\Rules\Model\ResourceModel\Rule\Grid\Collection em coleções Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory.
2) Para UI Grid, precisamos de uma coleção separada que representará a interface `Magento\Framework\Api\Search\SearchResultInterface` .
Ele contém os métodos padrão que permitem trabalhar com a Grade e os filtros. Essa classe pode ser personalizada de acordo com suas necessidades pessoais, alterando a maneira como a pesquisa por coleções funciona.
> app/code/Vendor/Rules/Model/ResourceModel/Rule/Grid/Collection.php
<?php namespace Vendor\Rules\Model\ResourceModel\Rule\Grid; use Vendor\Rules\Model\ResourceModel\Rule\Collection como RuleCollection; use Magento\Framework\Api\Search\SearchResultInterface; use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\Data\Collection\Db\FetchStrategyInterface; use Magento\Framework\Data\Collection\EntityFactory; use Magento\Framework\Event\ManagerInterface; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; use Psr\Log\LoggerInterface; class Collection estende RuleCollection e implementa SearchResultInterface { /** * Agregações * * @var \Magento\Framework\Search\AggregationInterface */ $agregações protegidas; /** * construtor * * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy * @param \Magento\Framework\Event\ManagerInterface $eventManager * @param $mainTable * @param $eventPrefix * @param $eventObject * @param $resourceModel * @param $model * @param $conexão * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource */ função pública __construct( EntityFactory $entityFactory, LoggerInterface $logger, FetchStrategyInterface $fetchStrategy, ManagerInterface $eventManager, $mainTable, $eventPrefix, $eventoObjeto, $resourceModel, $model = 'Magento\Framework\View\Element\UiComponent\DataProvider\Document', $ conexão = null, AbstractDb $resource = null ) { parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource); $this->_eventPrefix = $eventPrefix; $this->_eventObject = $eventObject; $this->_init($model, $resourceModel); $this->setMainTable($mainTable); } /** * @return \Magento\Framework\Search\AggregationInterface */ função pública getAgregações() { return $this->agregações; } /** * @param \Magento\Framework\Search\AggregationInterface $aggregations * @return $isto */ função pública setAggregations($aggregations) { $this->agregações = $agregações; } /** * Recupere todos os ids para coleta * Compatibilidade retroativa com a coleção EAV * * @param int $limit * @param int $offset * @return array */ função pública getAllIds($limit = null, $offset = null) { return $this->getConnection()->fetchCol($this->_getAllIdsSelect($limit, $offset), $this->_bindParams); } /** * Obter critérios de pesquisa. * * @return \Magento\Framework\Api\SearchCriteriaInterface|null */ função pública getSearchCriteria() { retornar nulo; } /** * Definir critérios de pesquisa. * * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria * @return $isto * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ função pública setSearchCriteria(SearchCriteriaInterface $searchCriteria = null) { retorne $isto; } /** * Obter contagem total. * * @return int */ função pública getTotalCount() { return $this->getSize(); } /** * Defina a contagem total. * * @param int $totalCount * @return $isto * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ função pública setTotalCount($totalCount) { retorne $isto; } /** * Definir lista de itens. * * @param \Magento\Framework\Api\ExtensibleDataInterface[] $items * @return $isto * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ função pública setItems(array $items = null) { retorne $isto; } } ?>
3) Modifique a coleção principal da maneira descrita abaixo (é importante, pois nossa coleção personalizada é herdada dela). Você deve fazer as seguintes alterações:
> app/code/Vendor/Rules/Model/ResourceModel/Rule/Collection.php
<?php namespace Vendor\Rules\Model\ResourceModel\Rule; class Collection estende \Magento\Rule\Model\ResourceModel\Rule\Collection\AbstractCollection { /** * Defina o modelo de recursos e determine o mapeamento de campos * * @return nulo */ função protegida _construct() { $this->_init('Fornecedor\Rules\Model\Rule', 'Fornecedor\Rules\Model\ResourceModel\Rule'); } /** * Filtre a coleta por data especificada. * Filtre a coleção apenas para regras ativas. * * @param string|null $now * @use $this->addStoreGroupDateFilter() * @return $isto */ função pública setValidationFilter($now = null) { if (!$this->getFlag('validation_filter')) { $this->addDateFilter($agora); $this->addIsActiveFilter(); $this->setOrder('sort_order', self::SORT_ORDER_DESC); $this->setFlag('validation_filter', true); } retorne $isto; } /** * Filtro de data ou data * * @param $agora * @return $isto */ função pública addDateFilter($now) { $this->getSelect()->where( 'from_date is null ou from_date <= ?', $ agora )->onde( 'to_date é nulo ou to_date >= ?', $ agora ); retorne $isto; } } ?>
4) Em seguida, remova a marcação antiga do layout de grade e adicione uma lista de interface do usuário lá:
> app/code/Vendor/Rules/view/adminhtml/layout/vendor_rules_example_rule_index.xml
<?xml version="1.0"?> <page xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <corpo> <referenceBlock name="menu"> <action method="setActive"> <argument name="itemId" xsi:type="string">Vendor_Rules::vendor_rules</argument> </action> </referenceBlock> <referenceBlock name="page.title"> <action method="setTitleClass"> <argument name="class" xsi:type="string">complexo</argument> </action> </referenceBlock> <referenceContainer name="content"> <uiComponent name="vendor_rules_rule_listing"/> </referenceContainer> </body> </page>
Basicamente, apenas adicionamos o mencionado ` vendor_rules_rule_listing ` no conteúdo da página (a ação principal), alteramos o status do menu do nosso produto para 'Ativo' e definimos a classe de título.
5) Na próxima etapa, criamos a listagem da interface do usuário, que será colocada aqui:
> app/code/Vendor/Rules/view/adminhtml/ui_component/vendor_rules_rule_listing.xml
<?xml version="1.0"?> <listing xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Ui/etc/ui_configuration.xsd"> <argument name="data" xsi:type="array"> <item name="js_config" xsi:type="array"> <item name="provider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing_data_source</item> <item name="deps" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing_data_source</item> </item> <item name="spinner" xsi:type="string">vendor_rules_rule_columns</item> <item name="botões" xsi:type="array"> <item name="adicionar" xsi:type="array"> <item name="name" xsi:type="string">adicionar</item> <item name="label" xsi:type="string" translate="true">Adicionar nova regra</item> <item name="class" xsi:type="string">primário</item> <item name="url" xsi:type="string">*/*/newaction</item> </item> </item> </argumento> <dataSource name="vendor_rules_rule_listing_data_source"> <argument name="dataProvider" xsi:type="configurableObject"> <argument name="class" xsi:type="string">VendorRulesRuleGridDataProvider</argument> <argument name="name" xsi:type="string">vendor_rules_rule_listing_data_source</argument> <argument name="primaryFieldName" xsi:type="string">rule_id</argument> <argument name="requestFieldName" xsi:type="string">rule_id</argument> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="update_url" xsi:type="url" path="mui/index/render"/> </item> </argumento> </argumento> <argument name="data" xsi:type="array"> <item name="js_config" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item> </item> </argumento> </dataSource> <container name="listing_top"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="template" xsi:type="string">ui/grid/barra de ferramentas</item> <item name="stickyTmpl" xsi:type="string">ui/grid/sticky/toolbar</item> </item> </argumento> <bookmark name="bookmarks"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="storageConfig" xsi:type="array"> <item name="namespace" xsi:type="string">vendor_rules_rule_listing</item> </item> </item> </argumento> </bookmark> <component name="columns_controls"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="columnsData" xsi:type="array"> <item name="provider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.vendor_rules_rule_columns</item> </item> <item name="component" xsi:type="string">Magento_Ui/js/grid/controls/columns</item> <item name="displayArea" xsi:type="string">dataGridActions</item> </item> </argumento> </component> <filters name="listing_filters"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="columnsProvider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.vendor_rules_rule_columns</item> <item name="storageConfig" xsi:type="array"> <item name="provider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.listing_top.bookmarks</item> <item name="namespace" xsi:type="string">current.filters</item> </item> <item name="templates" xsi:type="array"> <item name="filtros" 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 name="childDefaults" xsi:type="array"> <item name="provider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.listing_top.listing_filters</item> <item name="imports" xsi:type="array"> <item name="visible" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.vendor_rules_rule_columns.${ $.index }:visible</item> </item> </item> </item> <item name="observadores" xsi:type="array"> <item name="coluna" xsi:type="string">coluna</item> </item> </argumento> </filtros> <paging name="listing_paging"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="storageConfig" xsi:type="array"> <item name="provider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.listing_top.bookmarks</item> <item name="namespace" xsi:type="string">current.paging</item> </item> <item name="selectProvider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.vendor_rules_rule_columns.ids</item> </item> </argumento> </paging> </container> <columns name="vendor_rules_rule_columns"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="storageConfig" xsi:type="array"> <item name="provider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.listing_top.bookmarks</item> <item name="namespace" xsi:type="string">atual</item> </item> </item> </argumento> <selectionsColumn name="ids"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="resizeEnabled" xsi:type="boolean">falso</item> <item name="resizeDefaultWidth" xsi:type="string">55</item> <item name="indexField" xsi:type="string">rule_id</item> </item> </argumento> </selectionsColumn> <column name="rule_id"> <argument name="data" xsi:type="array"> <item name="js_config" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item> </item> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">textRange</item> <item name="dataType" xsi:type="string">texto</item> <item name="sorting" xsi:type="string">asc</item> <item name="align" xsi:type="string">esquerda</item> <item name="label" xsi:type="string" translate="true">ID</item> <item name="sortOrder" xsi:type="number">1</item> </item> </argumento> </coluna> <nome da coluna="nome"> <argument name="data" xsi:type="array"> <item name="js_config" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item> </item> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">texto</item> <item name="dataType" xsi:type="string">texto</item> <item name="align" xsi:type="string">esquerda</item> <item name="label" xsi:type="string" translate="true">Nome</item> </item> </argumento> </coluna> <column name="is_active"> <argument name="data" xsi:type="array"> <item name="options" xsi:type="array"> <item name="active" xsi:type="array"> <item name="value" xsi:type="string">1</item> <item name="label" xsi:type="string" translate="true">Ativo</item> </item> <item name="inativo" xsi:type="array"> <item name="valor" xsi:type="string">0</item> <item name="label" xsi:type="string" translate="true">Inativo</item> </item> </item> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">selecionar</item> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item> <item name="editor" xsi:type="string">selecionar</item> <item name="dataType" xsi:type="string">selecionar</item> <item name="label" xsi:type="string" translate="true">Está ativo</item> <item name="sortOrder" xsi:type="number">65</item> </item> </argumento> </coluna> <column name="sort_order"> <argument name="data" xsi:type="array"> <item name="js_config" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item> </item> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">texto</item> <item name="dataType" xsi:type="string">número</item> <item name="align" xsi:type="string">esquerda</item> <item name="label" xsi:type="string" translate="true">Prioridade</item> </item> </argumento> </coluna> <column name="from_date" class="Magento\Ui\Component\Listing\Columns\Date"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="sorting" xsi:type="string">desc</item> <item name="filter" xsi:type="string">dateRange</item> <item name="dataType" xsi:type="string">data</item> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item> <item name="label" xsi:type="string" translate="true">Iniciar</item> </item> </argumento> </coluna> <column name="to_date" class="Magento\Ui\Component\Listing\Columns\Date"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="sorting" xsi:type="string">desc</item> <item name="filter" xsi:type="string">dateRange</item> <item name="dataType" xsi:type="string">data</item> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item> <item name="label" xsi:type="string" translate="true">Fim</item> </item> </argumento> </coluna> <actionsColumn name="actions" class="Fornecedor\Rules\Ui\Component\Listing\Column\RuleActions"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="indexField" xsi:type="string">rule_id</item> <item name="urlEntityParamName" xsi:type="string">rule_id</item> <item name="sortOrder" xsi:type="number">70</item> </item> </argumento> </actionsColumn> </columns> <container name="sticky"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/grid/sticky/sticky</item> <item name="toolbarProvider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.listing_top</item> <item name="listingProvider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.vendor_rules_rule_columns</item> </item> </argumento> </container> </listagem>
A listagem ` dataSource ` contém um link para ` dataProvider ` – o tipo que criamos em ` di.xml `. Ele contém os dados de entrada necessários para o Grid.
A partir daqui, precisamos definir a chave arquivada — no nosso caso é ` rule_id `.
Além disso, você também pode adicionar seus botões personalizados, basta descrevê-los na seção 'botões'. Em nosso exemplo, adicionamos o botão padrão 'Adicionar' com um endereço ` */*/newaction ` ( * no caminho corresponde ao significado atual).
` container name=”listing_top” ` contém alguns componentes de listagem extras: filtros, paginação, etc. Você pode alterá-los de acordo com suas necessidades pessoais.
` columns name=“vendor_rules_rule_columns” ` contém as colunas que são quase as mesmas, como no Grid padrão. A única diferença significativa é uma nova coluna ` actionsColumn ` que apresenta um conjunto de ações: editar e excluir. Essas ações também podem ser estendidas, se necessário.
Como você deve ter notado, esta coluna tem uma nova classe. Vamos aprender como podemos criá-lo:
> app/code/Vendor/Rules/Ui/Component/Listing/Column/RuleActions.php
<?php namespace Vendor\Rules\Ui\Component\Listing\Column; class RuleActions estende \Magento\Ui\Component\Listing\Columns\Column { /** * Caminho de URL para editar * * @var string */ const URL_PATH_EDIT = 'vendor_rules/example_rule/edit'; /** * Caminho do URL para excluir * * @var string */ const URL_PATH_DELETE = 'vendor_rules/example_rule/delete'; /** * Construtor de URL * * @var \Magento\Framework\UrlInterface */ protegido $urlBuilder; /** * Construtor * * @param \Magento\Framework\UrlInterface $urlBuilder * @param \Magento\Framework\View\Element\UiComponent\ContextInterface $context * @param \Magento\Framework\View\Element\UiComponentFactory $uiComponentFactory * @param array $componentes * @param array $data */ função pública __construct( \Magento\Framework\UrlInterface $urlBuilder, \Magento\Framework\View\Element\UiComponent\ContextInterface $context, \Magento\Framework\View\Element\UiComponentFactory $uiComponentFactory, array $componentes = [], matriz $dados = [] ) { $this->urlBuilder = $urlBuilder; parent::__construct($context, $uiComponentFactory, $components, $data); } /** * Preparar fonte de dados * * @param array $dataSource * @return array */ função pública prepareDataSource(array $dataSource) { if (!isset($dataSource['data']['items'])) { return $dataSource; } foreach ($dataSource['data']['items'] as &$item) { if (!isset($item['rule_id'])) { Prosseguir; } $item[$this->getData('nome')] = [ 'editar' => [ 'href' => $this->urlBuilder->getUrl( estático::URL_PATH_EDIT, [ 'id' => $item['rule_id'], ] ), 'label' => __('Editar'), ], 'excluir' => [ 'href' => $this->urlBuilder->getUrl( estático::URL_PATH_DELETE, [ 'id' => $item['rule_id'], ] ), 'label' => __('Excluir'), 'confirmar' => [ 'title' => __('Excluir "${ $.$data.name }"'), 'message' => __('Tem certeza de que deseja excluir a regra "${ $.$data.name }" ?'), ], ], ]; } return $dataSource; } } ?>
Esta classe é responsável pelo processamento das ações do Grid. A partir daqui, é possível alterar as URLs ou o nome do parâmetro transmitido. No nosso caso, a chave é rule_id (é transmitida sob o nome 'id', para facilitar o entendimento de seu valor).
Se parece com isso:
Se você fez tudo do jeito certo, sua grade deve ficar assim:
Como podemos ver no exemplo, é muito fácil transformar o Grid padrão existente em UI. Além de estender a funcionalidade padrão do Grid, também permite simplificar o trabalho com esta parte da funcionalidade do Magento 2.
PS No próximo artigo da série, descreveremos a possibilidade de adicionar ações em massa e colunas extras.
Fique ligado!