Magento 2: Dodanie masowej akcji do własnego grida UI
Bardzo często chcemy wykonać zbiorcze modyfikowanie elementów. W Magento 2 komponentem UI, który umożliwi nam przeprowadzenie takich masowych akcji to MassAction. Jest on tylko dostępny dla listingu grida.
Dodanie masowej akcji do własnego grida wymaga:
- Dodanie kolumny selekcyjnej (jeśli nie istnieje) w konfiguracji ui komponentu,
- Zdefiniowanie akcji kontrolera,
- Dodanie masowej akcji i kolumny selekcyjnej w konfiguracji ui komponentu.
Po seriach wpisów związanych z księgą gości mamy prosty moduł Guestbook_AdminUI do jego obsługi w adminie. Powstały moduł zbudowany na komponencie UI, który pozwala na przegląd listy wpisów jak również oferuje podstawowe funkcjonalności CRUD, dzięki czemu możemy zarządzać wpisami.
Zajmijmy się więc dodaniem masowej akcji do grida guestbook. Dodamy możliwość wybierania wpisów oraz ich usunięcia.
Dodanie kolumny selekcyjnej
Zanim dodamy masową akcję, potrzebujemy kolumny selekcyjnej, która umożliwi nam wybieranie elementów do przetworzenia.
Wystarczy, że w konfiguracji grida, dla węzła <column> zdefiniujemy węzeł <selectionsColumn>. Oto dodana konfiguracja do pliku Anna/GuestbookAdminUI/view/adminhtml/ui_component/guestbook_listing.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
<?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"> <argument name="data" xsi:type="array"> <item name="js_config" xsi:type="array"> <item name="provider" xsi:type="string">guestbook_listing.guestbook_listing_data_source</item> </item> </argument> <settings> <spinner>guestbook_columns</spinner> <buttons> <button name="add"> <url path="*/*/new"/> <class>primary</class> <label translate="true">Add new entry</label> </button> </buttons> <deps> <dep>guestbook_listing.guestbook_listing_data_source</dep> </deps> </settings> <dataSource name="guestbook_listing_data_source" component="Magento_Ui/js/grid/provider"> <settings> <storageConfig> <param name="indexField" xsi:type="string">entry_id</param> </storageConfig> <updateUrl path="mui/index/render"/> </settings> <aclResource>Anna_GuestbookAdminUI::manage</aclResource> <dataProvider class="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider" name="guestbook_listing_data_source"> <settings> <requestFieldName>entry_id</requestFieldName> <primaryFieldName>entry_id</primaryFieldName> </settings> </dataProvider> </dataSource> <listingToolbar name="listing_top"> <settings> <sticky>true</sticky> </settings> <bookmark name="bookmarks"/> <columnsControls name="columns_controls"/> <filters name="listing_filters"/> <paging name="listing_paging"/> </listingToolbar> <columns name="guestbook_columns" class="Magento\Ui\Component\Listing\Columns"> <selectionsColumn name="ids" sortOrder="10"> <settings> <indexField>entry_id</indexField> </settings> </selectionsColumn> <column name="entry_id" sortOrder="20"> <settings> <filter>textRange</filter> <label translate="true">Entry Id</label> <sorting>asc</sorting> </settings> </column> <column name="customer_id" sortOrder="30"> <settings> <filter>text</filter> <label translate="true">Customer ID</label> </settings> </column> <column name="user_name" sortOrder="40"> <settings> <filter>text</filter> <label translate="true">User name</label> </settings> </column> <column name="subject" sortOrder="50"> <settings> <filter>text</filter> <label translate="true">Subject</label> </settings> </column> <column name="created_at" sortOrder="60"> <settings> <filter>text</filter> <label translate="true">Created At</label> </settings> </column> <actionsColumn name="actions" class="Anna\GuestbookAdminUI\Ui\Component\Listing\Column\Actions"> <settings> <indexField>entry_id</indexField> </settings> </actionsColumn> </columns> </listing> |
Dodana kolumna powinna się wyświetlić na początku. Z powodu cache’a możliwe, że zostanie wyświetlona na końcu.
Akcja kontrolera MassDelete
Do obsłużenia masowej akcji usuwania, będziemy potrzebowali dodać między innymi takie zależności do naszego kontrolera:
- Fabrykę kolekcji Anna\Guestbook\Model\ResourceModel\Guestbook\CollectionFactory,
- Klasę repozytorium, tutaj używamy Anna\Guestbook\Api\GuestbookRepositoryInterface,
- Klasę Magento\Ui\Component\MassAction\Filter, która pozwoli odfiltrować naszą kolekcję.
Stwórz plik Anna\GuestbookAdminUI\Controller\Adminhtml\Index\MassDelete.php o następującej zawartości:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
<?php declare(strict_types=1); namespace Anna\GuestbookAdminUI\Controller\Adminhtml\Index; use Anna\Guestbook\Api\GuestbookRepositoryInterface; use Anna\Guestbook\Model\ResourceModel\Guestbook\CollectionFactory; use Magento\Backend\App\Action; use Magento\Backend\App\Action\Context; use Magento\Backend\Model\View\Result\Redirect; use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Exception\LocalizedException; use Magento\Ui\Component\MassAction\Filter; use Psr\Log\LoggerInterface; class MassDelete extends Action implements HttpPostActionInterface { /** * Authorization level of a basic admin session * * @see _isAllowed() */ const ADMIN_RESOURCE = 'Anna_GuestbookAdminUI::manage'; /** * Massactions filter * * @var Filter */ protected $filter; /** * @var CollectionFactory */ protected $collectionFactory; /** * @var GuestbookRepositoryInterface */ private $guestbookRepository; /** * @var LoggerInterface */ private $logger; /** * @param Context $context * @param Filter $filter * @param CollectionFactory $collectionFactory * @param GuestbookRepositoryInterface|null $productRepository * @param LoggerInterface|null $logger */ public function __construct( Context $context, Filter $filter, CollectionFactory $collectionFactory, GuestbookRepositoryInterface $productRepository, LoggerInterface $logger ) { $this->filter = $filter; $this->collectionFactory = $collectionFactory; $this->guestbookRepository = $productRepository; $this->logger = $logger; parent::__construct($context); } /** * Mass Delete Action * * @return Redirect * @throws LocalizedException */ public function execute(): Redirect { $collection = $this->filter->getCollection($this->collectionFactory->create()); $entryDeleted = 0; $entryDeletedError = 0; /** @var \Anna\Guestbook\Model\Guestbook $entry */ foreach ($collection->getItems() as $entry) { try { $this->guestbookRepository->delete($entry); $entryDeleted++; } catch (LocalizedException $exception) { $this->logger->error($exception->getLogMessage()); $entryDeletedError++; } } if ($entryDeleted) { $this->messageManager->addSuccessMessage( __('A total of %1 record(s) have been deleted.', $entryDeleted) ); } if ($entryDeletedError) { $this->messageManager->addErrorMessage( __( 'A total of %1 record(s) haven\'t been deleted. Please see server logs for more details.', $entryDeletedError ) ); } return $this->resultFactory->create(ResultFactory::TYPE_REDIRECT)->setPath('guestbook/index/index'); } } |
Jako że jest to metoda typu post, implementuje ona interfejs Magento\Framework\App\Action\HttpPostActionInterface. Logika jest prosta: przetworzyć żądanie, następnie przekierować użytkownika na stronę główną grida i wyświetlić komunikat o statusie operacji.
Dodanie Masowej Akcji w konfiguracji ui komponentu
Podpięcie masowej akcji ustawiane jest dla komponentu listingToolbar. Wewnątrz niego możemy zdefiniować konfigurację dla komponentu MassAction, który pozwoli dodać akcję. W konfiguracji ui komponentu guestbook_listing.xml potrzebujemy dla węzła <listingToolbar> dodać nowy węzeł <massaction>, gdzie dla danej akcji definiujemy węzeł <action> wraz z konfiguracją:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
<?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"> <argument name="data" xsi:type="array"> <item name="js_config" xsi:type="array"> <item name="provider" xsi:type="string">guestbook_listing.guestbook_listing_data_source</item> </item> </argument> <settings> <spinner>guestbook_columns</spinner> <buttons> <button name="add"> <url path="*/*/new"/> <class>primary</class> <label translate="true">Add new entry</label> </button> </buttons> <deps> <dep>guestbook_listing.guestbook_listing_data_source</dep> </deps> </settings> <dataSource name="guestbook_listing_data_source" component="Magento_Ui/js/grid/provider"> <settings> <storageConfig> <param name="indexField" xsi:type="string">entry_id</param> </storageConfig> <updateUrl path="mui/index/render"/> </settings> <aclResource>Anna_GuestbookAdminUI::manage</aclResource> <dataProvider class="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider" name="guestbook_listing_data_source"> <settings> <requestFieldName>entry_id</requestFieldName> <primaryFieldName>entry_id</primaryFieldName> </settings> </dataProvider> </dataSource> <listingToolbar name="listing_top"> <settings> <sticky>true</sticky> </settings> <bookmark name="bookmarks"/> <columnsControls name="columns_controls"/> <filters name="listing_filters"/> <paging name="listing_paging"/> <massaction name="listing_massaction"> <action name="delete"> <settings> <confirm> <message translate="true">Are you sure you want to delete selected items?</message> <title translate="true">Delete items</title> </confirm> <url path="guestbook/index/massDelete"/> <type>delete</type> <label translate="true">Delete</label> </settings> </action> </massaction> </listingToolbar> <columns name="guestbook_columns" class="Magento\Ui\Component\Listing\Columns"> <selectionsColumn name="ids" sortOrder="10"> <settings> <indexField>entry_id</indexField> </settings> </selectionsColumn> <column name="entry_id" sortOrder="20"> <settings> <filter>textRange</filter> <label translate="true">Entry Id</label> <sorting>asc</sorting> </settings> </column> <column name="customer_id" sortOrder="30"> <settings> <filter>text</filter> <label translate="true">Customer ID</label> </settings> </column> <column name="user_name" sortOrder="40"> <settings> <filter>text</filter> <label translate="true">User name</label> </settings> </column> <column name="subject" sortOrder="50"> <settings> <filter>text</filter> <label translate="true">Subject</label> </settings> </column> <column name="created_at" sortOrder="60"> <settings> <filter>text</filter> <label translate="true">Created At</label> </settings> </column> <actionsColumn name="actions" class="Anna\GuestbookAdminUI\Ui\Component\Listing\Column\Actions"> <settings> <indexField>entry_id</indexField> </settings> </actionsColumn> </columns> </listing> |
Ostatnim krokiem, jak zawsze, jest wyczyszczenie cache i sprawdzenie zmian.
Magento 2: Dodanie masowej akcji do istniejącego grida - Web Programming
15 listopada 2023 @ 01:56
[…] jak poprzednio we wpisie, dodamy kolumnę selekcyjną, zdefiniujemy przykładową akcję i dołączymy odpowiednio […]