Créer une grille (uiComponent listing) dans l'administration magento 2

Ce tutoriel est le 7eme d’une longue série de tutoriel magento2. Il sera mis à jour au fur et à mesure des évolutions de la plateforme. Dans le dernier épisode, vous avez appris à créer un model et interagir avec la base de donnée de magento2. Si vous ne connaissez pas magento (v1) ce n’est pas grave, je vais en parler bien sur mais il n’est pas nécessaire de connaître la plateforme magento (v1) pour maîtriser ce tutoriel sur magento2, assurez vous par contre d'avoir fait les 6 tutoriaux précédents. Donc comme je le disais, dans le tutoriel précédent nous avons vu Comment ajouter son module à la partie administration (backend) de magento2 ! Nous allons maintenant voir comment ajouter dans notre interface d'administration magento, une grille et un formulaire magento2 pour le CRUD (ajout, modification, suppression, suppression de masse) de nos contact.Pour cela, on va repartir des fichiers de notre tutoriel précédent.

Créer le controlleur pour la grid magento2

Tout dabord, nous allons créer notre grid magento2 qui nous permettra de visualiser nos contacts dans le backoffice. Pour cela commencez par éditer l'action Index de votre controller Contact (/Pfay/Contacts/Controller/Adminhtml/Contact/Index.php) comme ceci pour qu'il charge et qu'il affiche votre layout:

namespace Pfay\Contacts\Controller\Adminhtml\Contact;

class Index extends \Magento\Backend\App\Action
{
    /**
     * Index action
     *
     * @return void
     */
    public function execute()
    {
        $this->_view->loadLayout();
        $this->_view->renderLayout();
    }
}

Créer le fichier de layout de la grid magento2 et le uiComponent "listing"

Allez ensuite créer le fichier de layout /Pfay/Contacts/view/adminhtml/layout/contacts_contact_index.xml Comme ceci :

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <uiComponent name="contacts_test_listing"/>
        </referenceContainer>
    </body>
</page>

Ici on lui dit d'aller chercher note uiComponent et de le mettre dans le container "content" de notre théme. On va lui donner le nom "contacts_test_listing" (faites attention au nom que vous donnez ici car on va l'utiliser pour créer le fichier suivant). Cet uiComponent magento2 est comme vous vous en doutez notre Grid.
On va donc définir notre uiComponent.
Créez le dossier /app/code/Pfay/Contacts/view/adminhtml/ui_component/ avec dedans le fichier contacts_test_listing.xml suivant :
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">

    <!-- main part of the grid -->
    <argument name="data" xsi:type="array">
        <!-- define where to find the date source -->
        <item name="js_config" xsi:type="array">
            <item name="provider" xsi:type="string">contacts_test_listing.contacts_test_listing_data_source</item>
            <item name="deps" xsi:type="string">contacts_test_listing.contacts_test_listing_data_source</item>
        </item>
        <!-- define where to find the columns -->
        <item name="spinner" xsi:type="string">contacts_test_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 a new Contact</item>
                <item name="class" xsi:type="string">primary</item>
                <item name="url" xsi:type="string">*/*/newAction</item>
            </item>
        </item>
    </argument>

    <!-- define the date source (must be the same than in argument/item/provider and argument/js_config/deps -->
    <dataSource name="contacts_contact_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <!-- unique name for the grid -->
            <argument name="class" xsi:type="string">ContactsGridDataProvider</argument>
            <!-- name of the data source same as in argument/js_config/provider -->
            <argument name="name" xsi:type="string">contacts_test_listing_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">pfay_contacts_id</argument>
            <argument name="requestFieldName" xsi:type="string">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">pfay_contacts_id</item>
                    </item>
                </item>
            </argument>
        </argument>
    </dataSource>

    <!-- define the columns of my grid -->
    <columns name="contacts_test_columns">

        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <!-- Bookmarks behaviour -->
                <item name="storageConfig" xsi:type="array">
                    <item name="provider" xsi:type="string">contacts_test_listing.contacts_test_listing.listing_top.bookmarks</item>
                    <item name="namespace" xsi:type="string">current</item>
                </item>
                <item name="childDefaults" xsi:type="array">
                    <item name="controlVisibility" xsi:type="boolean">true</item>
                    <item name="storageConfig" xsi:type="array">
                        <item name="provider" xsi:type="string">contacts_test_listing.contacts_test_listing.listing_top.bookmarks</item>
                        <item name="root" xsi:type="string">columns.${ $.index }</item>
                        <item name="namespace" xsi:type="string">current.${ $.storageConfig.root}</item>
                    </item>
                </item>
            </item>
        </argument>

        <selectionsColumn name="ids">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <!-- define which field will be used as ID -->
                    <item name="indexField" xsi:type="string">pfay_contacts_id</item>
                </item>
            </argument>
        </selectionsColumn>

        <!-- Column ID -->
        <column name="pfay_contacts_id">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">textRange</item>
                    <item name="sorting" xsi:type="string">asc</item>
                    <item name="label" xsi:type="string" translate="true">ID</item>
                </item>
            </argument>
        </column>
        <!-- Column name -->
        <column name="name">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="visible" xsi:type="boolean">true</item>
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="formElement" xsi:type="string">input</item>
                    <item name="source" xsi:type="string">contact</item>
                    <item name="dataScope" xsi:type="string">name</item>
                    <item name="label" xsi:type="string" translate="true">Name</item>
                    <item name="filter" xsi:type="string">text</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">true</item>
                    </item>
                </item>
            </argument>
        </column>
        <!-- Column email -->
        <column name="email">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="visible" xsi:type="boolean">true</item>
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="formElement" xsi:type="string">input</item>
                    <item name="source" xsi:type="string">contact</item>
                    <item name="dataScope" xsi:type="string">email</item>
                    <item name="label" xsi:type="string" translate="true">Email</item>
                    <item name="filter" xsi:type="string">text</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">true</item>
                    </item>
                </item>
            </argument>
        </column>
        <!-- action columns edit and delete -->
        <actionsColumn name="actions" class="Pfay\Contacts\Ui\Component\Listing\Column\ContactsActions">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="resizeEnabled" xsi:type="boolean">false</item>
                    <item name="resizeDefaultWidth" xsi:type="string">107</item>
                    <item name="indexField" xsi:type="string">pfay_contacts_id</item>
                </item>
            </argument>
        </actionsColumn>
    </columns>
    
</listing>

Ce fichier à l'air complexe mais il ne l'est pas tant que ca, c'est juste une balise listing qui contient 4 balises child :
- argument :
Ici on déclare les data_sources à utiliser (ce qui fait le liens entre votre grid et la base de donnée) avec la balise js_config.
On déclare également le spinner c'est à dire le nom de la balise "columns" qu'on va utiliser dans notre grille.
On déclare ensuite nos boutons dans la balise buttons avec un nom, un label, une classe et une url cible.

- dataSource :
Ici on défini le dataProvider (l'objet qui va aller chercher nos données en base de donnée). avec une balise "class" qui permet de définir le nom de l'objet qu'on va utiliser. Cet objet sera défini plus tard dans le di.xml (fichier d'njection de dépendances).
On donne un nom à notre dataSource via l'attribut "name" puis on lui donne le champs à utiliser comme id pour la grid dans la base de donnée ("primaryFieldName") et pour la request ("requestFieldName").
On défini ensuite dans "config" le component à utiliser (ici "Magento_Ui/js/grid/provider") et l'identifiant dans notre bdd "indexField" qui a ici la valeur "pfay_contacts_id".

- columns :
On l'a défini plus haut dans "spinner" de la section "argument", ici elle s'apelle listing_columns.
Cette zone vas nous permettre de définir nos colones avec l'identifiant à utiliser pour se retrouver, le type de champs et de filtre à utiliser pour la grid (attention a ca pour la suite), le type de sorting qu'on va utiliser et un label.


Dans l'actionsColumn on a défini la classe à utiliser pour définir les bouttons à savoir ContactsActions. Créez donc le fichier app/code/Pfay/Contacts/Ui/Component/Listing/Column/ContactsActions.php correspondant :

<?php
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Pfay\Contacts\Ui\Component\Listing\Column;

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

/**
 * Class DepartmentActions
 */
class ContactsActions extends Column
{
    /**
     * @var UrlInterface
     */
    protected $urlBuilder;

    /**
     * @param ContextInterface $context
     * @param UiComponentFactory $uiComponentFactory
     * @param UrlInterface $urlBuilder
     * @param array $components
     * @param array $data
     */
    public function __construct(
        ContextInterface $context,
        UiComponentFactory $uiComponentFactory,
        UrlInterface $urlBuilder,
        array $components = [],
        array $data = []
    ) {
        $this->urlBuilder = $urlBuilder;
        parent::__construct($context, $uiComponentFactory, $components, $data);
    }

    /**
     * Prepare Data Source
     *
     * @param array $dataSource
     * @return array
     */
    public function prepareDataSource(array $dataSource)
    {
        if (isset($dataSource['data']['items'])) {
            foreach ($dataSource['data']['items'] as &$item) {
                $item[$this->getData('name')]['edit'] = [
                    'href' => $this->urlBuilder->getUrl(
                        'contacts/test/edit',
                        ['id' => $item['pfay_contacts_id']]
                    ),
                    'label' => __('Edit'),
                    'hidden' => false,
                ];
                $item[$this->getData('name')]['delete'] = [
                    'href' => $this->urlBuilder->getUrl(
                        'contacts/test/delete',
                        ['id' => $item['pfay_contacts_id']]
                    ),
                    'label' => __('Delete'),
                    'hidden' => false,
                ];
            }
        }

        return $dataSource;
    }
}

C'est tout..pour le moment, c'était pas si compliqué vous voyez :)

Ensuite rappelez vous que dans ce fichier on a défini un objet qui s'apelle ContactsGridDataProvider, actuellement il ne correspond à rien donc on va déclarer cet object qu'on appelle un dataProvider en le définissant dans le fichier d'injection de dépendance (di.xml).

Créez donc le fichier app/code/Pfay/Contacts/etc/di.xml comme ceci :

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

    <virtualType name="ContactsGridDataProvider" type="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider">
        <arguments>
            <argument name="collection" xsi:type="object" shared="false">Pfay\Contacts\Model\ResourceModel\Contact\Collection</argument>
            <argument name="filterPool" xsi:type="object" shared="false">ContactsGirdFilterPool</argument>
        </arguments>
    </virtualType>

    <virtualType name="ContactsGridDataProvider" type="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider">
        <arguments>
            <argument name="collection" xsi:type="object" shared="false">Pfay\Contacts\Model\ResourceModel\Contact\Collection</argument>
            <argument name="filterPool" xsi:type="object" shared="false">ContactsGirdFilterPool</argument>
        </arguments>
    </virtualType>

    <virtualType name="ContactsGirdFilterPool" type="Magento\Framework\View\Element\UiComponent\DataProvider\FilterPool">
        <arguments>
            <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>
            </argument>
        </arguments>
    </virtualType>

    <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
        <arguments>
            <argument name="collections" xsi:type="array">
                <item name="contacts_test_listing_data_source" xsi:type="string">Pfay\Contacts\Model\ResourceModel\Contact\Collection</item>
            </argument>
        </arguments>
    </type>

    <virtualType name="Pfay\Contacts\Model\ResourceModel\Contact\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult">
        <arguments>
            <argument name="mainTable" xsi:type="string">pfay_contacts</argument>
            <argument name="resourceModel" xsi:type="string">Pfay\Contacts\Model\ResourceModel\Contact</argument>
        </arguments>
    </virtualType>

</config>
Ici c'est pareil ca a l'air compliqué mais en fait c'est trés simple :
1- On définit un virtualType ContactsGridDataProvider, on lui passe en argment la classe de notre collection Pfay\Contacts\Model\ResourceModel\Contact\Collection et on lui dit d'utiliser un "filterPool" avec le nom "ContactsGirdFilterPool".
2- On définit le "ContactsGirdFilterPool" qu'on vient de déclarer en lui passant un item "regular" et un item "fulltext".
3- on crée le type cdontacts_test_listing_data_source qu'on utilise plus haut dans notre XML (attention à bien mettre le même nom) et on définit que cela va utiliser notre collection.
4- on crée un virtualType SearchResult, on lui passe en nom notre collection et on lui dit d'utiliser notre table "pfay_contacts" et le resourceModel "Pfay\Contacts\Model\ResourceModel\Contact" pour se repérer.

Allez sur votre interface d'admin et vous devriez maintenant voir votre grille aparaitre.

Si cela n'est pas le cas, n'hésitez pas à vider votre cache, lancer la commande d'update (voir les tutos précédents) et remettre les bons droits sur vos fichiers.

Ajouter le bouton add à notre grid magento2

Dans notre grid component ( /app/code/Pfay/Contacts/view/adminhtml/ui_component/contacts_test_listing.xml ) ajoutez dans argument le code suivant pour ajouter le bouton "add" à notre grid :

    <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 a new contact</item>
            <item name="class" xsi:type="string">primary</item>
            <item name="url" xsi:type="string">*/*/newAction</item>
        </item>
    </item>
    
C'est dans l'item "buttons" que vous allez mettre tous vos bouttons. Cet élément est un "array", vous pouvez donc mettre plusieurs items à la suite. Chaque element sera un button, pour lequel vous définissez un nom, un label, la classe et l'url vers laquelle on est redirigé quand on clique dessus (ici on redirige vers */*/add ce qui veut dire qu'on va rediriger vers l'action Add du même dossier que notre controlleur actuel. On crée donc un fichier /app/code/Pfay/Contacts/Controller/Adminhtml/Test/Add.php qui contiendra notre action :

<?php
namespace Pfay\Contacts\Controller\Adminhtml\Test;
use Magento\Backend\App\Action;

class Add extends \Magento\Backend\App\Action
{
    public function execute()
    {
       die('test add');
    }
}

Rechargez votre page et cliquez sur le bouton "Add a new Contact" qui apparait maintenant, vous devriez arriver sur votre conrolleur qui affiche une page blanche avec "test add". Nous verrons dans le prochain tutoriel comment afficher le formulaire qui permettra d'ajouter un nouveau contact.

Les éléments optionnels :

Les elements optionels son mis dans le "container". le "container" est la 4eme balise non obligatoire de l'élément listing apres "argument", "dataSource", et "columns" qui sont eux obligatoire. Il prend au minimum un argument data qui permet de définir son template à savoir ui/grid/toolbar. Voici comment l'intégrer dans notre fichier /app/code/Pfay/Contacts/view/adminhtml/ui_component/contacts_test_listing.xml

 <container name="listing_top">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="template" xsi:type="string">ui/grid/toolbar</item>
        </item>
    </argument>
    
    <!-- we put the others elements here -->

</container>

c'est donc dans cet element "container" que nous mettrons les éléments optionels suivants de ce tutoriel.

Ajouter le conteneur "columns controls"

Le columns controls est un element qui permet de gérer les colones de votre grid à la volée, vous pourrez ajouter / supprimer une colone / remettre la grid à un état de base et vous pourrez sauvegarder l'état de la grid dans la session.
Voici le code à intégrer dans le "container" pour afficher le columns controls :

 <container 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">contacts_test_listing.contacts_test_listing.contacts_test_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>
            </argument>
        </container>
        

Les Bookmarks

Les bookmarks permettent de sauvegarder l'état de la grille que vous avez modifié avec l'élément "columns_control" crée précédemment. Voici comment intégrer cet élément "bookmark" dans le "container" :

 <bookmark name="bookmarks">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="component" xsi:type="string">Magento_Ui/js/grid/controls/bookmarks/bookmarks</item>
                    <item name="displayArea" xsi:type="string">dataGridActions</item>
                    <item name="storageConfig" xsi:type="array">
                        <item name="saveUrl" xsi:type="url" path="*/*/save"/>
                        <item name="deleteUrl" xsi:type="url" path="*/*/delete"/>
                        <item name="namespace" xsi:type="string">contact_test_listing</item>
                    </item>
                </item>
            </argument>
        </bookmark>
        
Faites attention à bien mettre le namespace et à bien définir vos urls.

La pagination

La pagination des grid sous magento2 est super bien faite et trés facile à intégrer, il suffit juste de faire attention aux 2 chemins "provider" et "selectProvider".
Voici le code à insérer :

 <paging name="listing_paging">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="storageConfig" xsi:type="array">
                <!-- we put here the path to the bookmarks element -->
                <item name="provider" xsi:type="string">contacts_test_listing.contacts_test_listing.listing_top.bookmarks</item>
                <item name="namespace" xsi:type="string">current.paging</item>
            </item>
            <!-- we put here the path to the element pfay_contact_ids of contacts_test_columns  element -->
            <item name="selectProvider" xsi:type="string">contacts_test_listing.contacts_test_listing.contacts_test_columns.pfay_contacts_id</item>
            <item name="displayArea" xsi:type="string">bottom</item>
        </item>
    </argument>
</paging>
    

Les filtres de la grille magento2

Pouvoir filtrer le tableau peut parfois être pratique, pour cela un élément "filter" peu êre ajouté à la grid magento. Voici comment faire :

 <filters name="listing_filters">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="storageConfig" xsi:type="array">
                        <item name="provider" xsi:type="string">contacts_test_listing.contacts_test_listing.listing_top.bookmarks</item>
                        <item name="namespace" xsi:type="string">curren.filters</item>
                    </item>
                    <item name="childDefaults" xsi:type="array">
                        <item name="provider" xsi:type="string">contacts_test_listing.contacts_test_listing.listing_top.listing_filters</item>
                        <item name="imports" xsi:type="array">
                            <item name="visible" xsi:type="string">contacts_test_listing.contacts_test_listing.listing_top.bookmarks:current.columns.${ $.index }.visible</item>
                        </item>
                    </item>
                </item>
            </argument>
        </filters>
        
Par défaut, il prend bien tous les champs disponible sur la grid, il sait comment filtrer grâce à l'item "filter" de vos "columns" comme ceux ci :

 ici type text :
  <item name="filter" xsi:type="string">text</item>
 
 ici type textRange :
  <item name="filter" xsi:type="string">textRange</item>
  

Les Mass Actions sous magento2

Vous voulez pouvoir séléctionner plusieurs lignes de votre grid pour les supprimer en une seule fois ou faire un autre traitement spécifique sur toutes les lignes sélectionnées en même temps ? Les Mass Actions sont faites pour cela. Tout d'abord il va faloir ajouter les input sur le bord de notre grid pour pouvoir selectioner les lignes, donc dans "columns" rajoutez ceci avant les "column" :

<selectionsColumn name="ids">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <!-- define which field will be used as ID -->
            <item name="indexField" xsi:type="string">pfay_contacts_id</item>
        </item>
    </argument>
</selectionsColumn>
        
    
Vous voyez maintenant apparaitre les checkbox sur le coté qui vous permettent de sélectionner plusieurs lignes. Voici comment Intégrer la selectbox qui permet de sélectionner l'action à effectuer une fois qu'on a selectionné nos lignes :

 <massaction name="listing_massaction">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <!-- we put here the path to the element pfay_contact_ids of contacts_test_columns  element -->
                    <item name="selectProvider" xsi:type="string">contacts_test_listing.contacts_test_listing.contacts_test_columns.ids</item>
                    <item name="displayArea" xsi:type="string">bottom</item>
                    <item name="indexField" xsi:type="string">pfay_contacts_id</item>
                </item>
            </argument>
            <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 Selected</item>
                        <item name="url" xsi:type="url" path="*/*/massDelete"/>
                        <item name="confirm" xsi:type="array">
                            <item name="title" xsi:type="string" translate="true">Delete all selected contacts</item>
                            <item name="message" xsi:type="string" translate="true">Do you want to delete all the selected contacts?</item>
                        </item>
                    </item>
                </argument>
            </action>
        </massaction>
    
Ici c'est pareil, il faut bien faire attention à ce qu'on va rentrer comme chemin pour le "selectProvider" et ensuite on ajoute dans actions à la suite les unes des autres. Afin de préparer le prochain tutoriel, nous allons créer le controlleur MassDelete. C'est la ou on sera redirigé quand on selectionnera notre action (*/*/massDelete). Créez donc le fichier suivant /app/code/Pfay/Contacts/Controller/Adminhtml/Test/MassDelete.php :

<?php
namespace Pfay\Contacts\Controller\Adminhtml\Test;
use Magento\Backend\App\Action;
use Pfay\Contacts\Model\Contact;

class MassDelete extends \Magento\Backend\App\Action
{
    public function execute()
    {
        $ids = $this->getRequest()->getParam('selected', []);
        if (!is_array($ids) || !count($ids)) {
            $resultRedirect = $this->resultRedirectFactory->create();
            return $resultRedirect->setPath('*/*/index', array('_current' => true));
        }
        foreach ($ids as $id) {
            if ($contact = $this->_objectManager->create(Contact::class)->load($id)) {
                $contact->delete();
            }
        }
        $this->messageManager->addSuccess(__('A total of %1 record(s) have been deleted.', count($ids)));

        $resultRedirect = $this->resultRedirectFactory->create();
        return $resultRedirect->setPath('*/*/index', array('_current' => true));
    }
}
Ici on vérifie que le paramétre "selected" a bien été envoyé et que c'est bien un array non vide sinon on redirige vers la grid. si c'est ok, alors on parcours les ids et on supprime les contacts. Ensuite on redirige vers la grid. Et voila si vous utilisez votre mass actions vous devriez arriver sur votre action.

Créer un champs de recherche dans l'admin magento2

pour créer un champs de recherche sur l'admin de magento, il faut ajouter un élément optionnel dans le container qui s'appellera "filterSearch" comme ceci : Dans app/code/Pfay/Contacts/view/adminhtml/ui_component/contacts_test_listing.xml ajoutez donc :

     <!-- Filter Search -->
        <filterSearch name="fulltext">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="provider" xsi:type="string">contacts_test_listing.contacts_test_listing_data_source</item>
                    <item name="chipsProvider" xsi:type="string">contacts_test_listing.contacts_test_listing.listing_top.listing_filters_chips</item>
                    <item name="storageConfig" xsi:type="array">
                        <item name="provider" xsi:type="string">contacts_test_listing.contacts_test_listing.listing_top.bookmarks</item>
                        <item name="namespace" xsi:type="string">current.search</item>
                    </item>
                </item>
            </argument>
        </filterSearch>
        
Pour que la recherche fonctionne il va faloir par contre mettre à jour votre table pour ajouter l'index.
Editez donc votre fichier upgrade ( app/code/Pfay/Contacts/Setup/UpgradeSchema.php ) comme ceci :

<?php
namespace Pfay\Contacts\Setup;

use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Catalog\Model\ResourceModel\Product\Gallery;
use Magento\Catalog\Model\Product\Attribute\Backend\Media\ImageEntryConverter;

/**
 * Upgrade the Catalog module DB scheme
 */
class UpgradeSchema implements UpgradeSchemaInterface
{
    /**
     * {@inheritdoc}
     */
    public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();

        if (version_compare($context->getVersion(), '0.2.0', '<')) {

            $tableName = $setup->getTable('pfay_contacts');
            $setup->getConnection()->addColumn($tableName, 'comment', [
                'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                'length'    => 255,
                'unsigned' => true,
                'nullable' => false,
                'default' => '0',
                'comment' => 'Comment'
            ]);
        }else  if (version_compare($context->getVersion(), '0.3.0', '<')) {

            /**
             * Add full text index to our table department
             */

            $tableName = $setup->getTable('pfay_contacts');
            $fullTextIntex = array('name','email'); // Column with fulltext index, you can put multiple fields
            $setup->getConnection()->addIndex(
                $tableName,
                $setup->getIdxName($tableName, $fullTextIntex, \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT),
                $fullTextIntex,
                \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT
            );
        }
        $setup->endSetup();
    }
} 
Vous remarquez ici que pour la version 0.3.0, on rajoutes pour la table pfay_contacts un index sur le nom et l'email de type FULLTEXT. c'est cet index qui sera utilisé pour filtrer notre grid d'admin magento2. Nous verrons dans le prochain tutoriel comment créer les actions create / delete / edit et le formulaire de création et d'édition lié à notre grid et notre objet contact ! C'est la fin de ce tutoriel sur les grilles magento 2, félicitation à vous qui avez suivi ce tutoriel jusqu'au bout. Si ce tutoriel vous à plus ou que vous avez une question, partagez cet article sur twitter s'il vous plait ! Merci à ceux qui le feront.
Documents disponibles pour cet article :
Questions sur cette leçon
Pas de questions pour cette leçon. Soyez le premier !

Vous devez etre connecté pour demander de l'aide sur une leçon.