Łatwy sposób na dodanie zestawu pól z polami do formularza interfejsu użytkownika
Opublikowany: 2016-08-23W tym artykule stworzymy prosty moduł, który doda zestaw pól z polami w formularzu UI edycji produktu. Ponadto stworzymy obserwatora, który przechwyci te dane podczas zapisywania produktu.
Najpierw musimy stworzyć moduł Vendor_Product:
1. Utwórz katalog app/code/Vendor/Product
2. Utwórz plik rejestracyjny app/code/Vendor/Product/registration.php o następującej zawartości:
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Produkt_Dostawcy', __KATALOG__ ); ?>
Utwórz plik kompozytora (jeśli planujesz przenieść moduł) app/code/Vendor/Module/composer.json :
{ "name": "dostawca/moduł-produkt", "opis": "nie dotyczy", "typ": "magento2-moduł", "wersja": "1.0.0", "licencja": [ "OSL-3.0", "AFL-3.0" ], "automatyczne ładowanie": { "akta": [ "rejestracja.php" ], "psr-4": { "Dostawca\\Produkt\\": "" } } }
Teraz utwórz główny plik XML modułu app/code/Vendor/Product/etc/module.xml z zależnością z modułu Magento_Catalog, ponieważ nasze okno modalne zostanie dodane do jego formularza:
<?xml version="1.0"?> <config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Vendor_Product" setup_version="1.0.0"> <sekwencja> <nazwa modułu="Magento_Catalog"/> </sequence> </moduł> </config>
Włącz moduł, wpisując: bin/magento module:enable Vendor_Product i bin/magento setup:upgrade w głównym katalogu Magento.
Następnie dodaj zawartość modułu: metadane formularza interfejsu użytkownika i typ wirtualny do jego dodania.
Utwórz plik app/code/Vendor/Product/etc/adminhtml/di.xml. Umieścimy wewnątrz modyfikator:
<?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="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool"> <argumenty> <argument name="modyfikatory" xsi:type="array"> <item name="niestandardowy zestaw pól" xsi:type="array"> <item name="class" xsi:type="string">Dostawca\Produkt\Ui\DataProvider\Produkt\Form\Modifier\CustomFieldset</item> <item name="sortOrder" xsi:type="number">10</item> </item> </argument> </arguments> </virtualType> </config>
Modyfikator odpowiada za dodawanie danych oraz pewne manipulacje elementami i komponentami formularza UI. Istnieją 2 główne metody, które pochodzą z interfejsu modyfikatora (powinny zawsze być obecne):
<?php /** * Prawa autorskie 2016 Magento. Wszelkie prawa zastrzeżone. * Zobacz COPYING.txt, aby uzyskać szczegółowe informacje o licencji. */ przestrzeń nazw Magento\Ui\DataProvider\Modifier; /** * Interfejs modyfikatora klasy */ Modyfikator interfejsuInterfejs { /** * @param array $data * @tablica powrotu */ funkcja publiczna zmieńDane(tablica $dane); /** * @param array $meta * @tablica powrotu */ funkcja publiczna zmodyfikujMeta(tablica $meta); } ?>
W tym przykładzie użyjemy metody modyfikacjiMeta. Metoda modyfikacjiData zostanie wyjaśniona w następnym artykule.
Teraz utwórz plik modyfikatora (app/code/Vendor/Product/Ui/DataProvider/Product/Form/Modifier/CustomFieldset.php) z niestandardowym zestawem pól dla strony edycji produktu i wypełnij go polami:
<?php przestrzeń nazw Dostawca\Produkt\Ui\DataProvider\Produkt\Form\Modyfikator; użyj Magento\Catalog\Model\Locator\LocatorInterface; użyj Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; użyj Magento\Framework\Stdlib\ArrayManager; użyj Magento\Framework\UrlInterface; użyj Magento\Ui\Komponent\Kontener; użyj Magento\Ui\Component\Form\Fieldset; użyj Magento\Ui\Component\Form\Element\DataType\Number; użyj Magento\Ui\Component\Form\Element\DataType\Text; użyj Magento\Ui\Komponent\Formularz\Element\Input; użyj Magento\Ui\Komponent\Formularz\Element\Select; użyj Magento\Ui\Komponent\Formularz\Element\MultiSelect; użyj Magento\Ui\Komponent\Formularz\Pole; klasa CustomFieldset rozszerza AbstractModifier { // Indeksy składników const CUSTOM_FIELDSET_INDEX = 'niestandardowy_zestaw_pól'; const CUSTOM_FIELDSET_CONTENT = 'custom_fieldset_content'; const CONTAINER_HEADER_NAME = 'custom_fieldset_content_header'; // Nazwy pól const FIELD_NAME_TEXT = 'przykładowe_pole_tekstowe'; const FIELD_NAME_SELECT = 'example_select_field'; const FIELD_NAME_MULTISELECT = 'example_multiselect_field'; /** * @var \Magento\Catalog\Model\Locator\LocatorInterface */ chroniony lokalizator; /** * @var ArrayManager */ chroniony $arrayManager; /** * @var UrlInterface */ chroniony $urlBuilder; /** * @var array */ chroniony $meta = []; /** * @param LocatorInterface $locator * @param ArrayManager $arrayManager * @param UrlInterface $urlBuilder */ funkcja publiczna __konstrukcja( LocatorInterface $lokator, $arrayManager, UrlInterface $urlBuilder ) { $to->lokalizator = $lokalizator; $this->arrayManager = $arrayManager; $this->urlBuilder = $urlBuilder; } /** * Modyfikator danych, w naszym przykładzie nic nie robi. * * @param array $data * @tablica powrotu */ funkcja publiczna zmieńDane(tablica $dane) { zwróć $dane; } /** * Modyfikator metadanych: dodaje nasz zestaw pól * * @param array $meta * @tablica powrotu */ funkcja publiczna zmodyfikujMeta(tablica $meta) { $to->meta = $meta; $this->addCustomFieldset(); zwróć $to->meta; } /** * Połącz istniejące metadane z naszymi metadanymi (nie nadpisuj ich!) * * @zwrot nieważny */ funkcja chroniona addCustomFieldset() { $this->meta = array_merge_recursive( $this->meta, [ static::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(), ] ); } /** * Zadeklaruj naszą konfigurację zestawu pól * * @tablica powrotu */ funkcja chroniona getFieldsetConfig() { zwrócić [ 'argumenty' => [ 'dane' => [ 'konfiguracja' => [ 'label' => __('Tytuł pola'), 'componentType' => Fieldset::NAME, 'dataScope' => static::DATA_SCOPE_PRODUCT, // zapisz dane w danych produktu 'provider' => static::DATA_SCOPE_PRODUCT . '_źródło danych', 'ns' => statyczny::FORM_NAME, 'składany' => prawda, 'porządek sortowania' => 10, 'otwarte' => prawda, ], ], ], 'dzieci' => [ static::CONTAINER_HEADER_NAME => $this->getHeaderContainerConfig(10), static::FIELD_NAME_TEXT => $this->getTextFieldConfig(20), static::FIELD_NAME_SELECT => $this->getSelectFieldConfig(30), static::FIELD_NAME_MULTISELECT => $this->getMultiSelectFieldConfig(40), ], ]; } /** * Pobierz konfigurację dla kontenera nagłówka * * @param int $sortOrder * @tablica powrotu */ funkcja chroniona getHeaderContainerConfig($sortOrder) { zwrócić [ 'argumenty' => [ 'dane' => [ 'konfiguracja' => [ 'etykieta' => null, 'formElement' => Kontener::NAZWA, 'componentType' => Kontener::NAZWA, 'szablon' => 'ui/formularz/komponenty/kompleks', 'sortOrder' => $sortOrder, 'content' => __('Tu możesz wpisać dowolny tekst'), ], ], ], 'dzieci' => [], ]; } /** * Przykładowa konfiguracja pola tekstowego * * @param $sortOrder * @tablica powrotu */ funkcja chroniona getTextFieldConfig($sortOrder) { zwrócić [ 'argumenty' => [ 'dane' => [ 'konfiguracja' => [ 'label' => __('Przykładowe pole tekstowe'), 'formElement' => Pole::NAME, 'componentType' => Input::NAME, 'dataScope' => statyczny::FIELD_NAME_TEXT, 'dataType' => Numer::NAZWA, 'sortOrder' => $sortOrder, ], ], ], ]; } /** * Przykładowa konfiguracja pola wyboru * * @param $sortOrder * @tablica powrotu */ funkcja chroniona getSelectFieldConfig($sortOrder) { zwrócić [ 'argumenty' => [ 'dane' => [ 'konfiguracja' => [ 'label' => __('Opcje Wybierz'), 'componentType' => Pole::NAZWA, 'formElement' => Wybierz::NAME, 'dataScope' => statyczny::FIELD_NAME_SELECT, 'dataType' => Tekst::NAZWA, 'sortOrder' => $sortOrder, 'opcje' => $this->_getOptions(), 'widoczny' => prawda, 'wyłączone' => fałsz, ], ], ], ]; } /** * Przykładowa konfiguracja pola wielokrotnego wyboru * * @param $sortOrder * @tablica powrotu */ funkcja chroniona getMultiSelectFieldConfig($sortOrder) { zwrócić [ 'argumenty' => [ 'dane' => [ 'konfiguracja' => [ 'label' => __('Opcje wielokrotnego wyboru'), 'componentType' => Pole::NAZWA, 'formElement' => MultiSelect::NAME, 'dataScope' => statyczny::FIELD_NAME_MULTISELECT, 'dataType' => Tekst::NAZWA, 'sortOrder' => $sortOrder, 'opcje' => $this->_getOptions(), 'widoczny' => prawda, 'wyłączone' => fałsz, ], ], ], ]; } /** * Pobierz przykładowe opcje jako tablicę opcji: * [ * etykieta => ciąg, * wartość => identyfikator_opcji * ] * * @tablica powrotu */ funkcja chroniona _getOptions() { $opcje = [ 1 => [ 'etykieta' => __('Opcja 1'), 'wartość' => 1 ], 2 => [ 'etykieta' => __('Opcja 2'), 'wartość' => 2 ], 3 => [ 'etykieta' => __('Opcja 3'), 'wartość' => 3 ], ]; zwróć $opcje; } } ?>
W tym przykładzie musimy wziąć istniejące metadane formularza interfejsu użytkownika i połączyć je (nie przepisać!) z naszymi nowymi danymi:
<?php /** * Połącz istniejące metadane z naszymi metadanymi (nie nadpisuj ich!) * * @zwrot nieważny */ funkcja chroniona addCustomFieldset() { $this->meta = array_merge_recursive( $this->meta, [ static::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(), ] ); } ?>
Po zakończeniu dodaj nowy zestaw pól do metody getFieldsetConfig:
<?php /** * Zadeklaruj naszą konfigurację zestawu pól * * @tablica powrotu */ funkcja chroniona getFieldsetConfig() { zwrócić [ 'argumenty' => [ 'dane' => [ 'konfiguracja' => [ 'label' => __('Tytuł pola'), 'componentType' => Fieldset::NAME, 'dataScope' => static::DATA_SCOPE_PRODUCT, // zapisz dane w danych produktu 'provider' => static::DATA_SCOPE_PRODUCT . '_źródło danych', 'ns' => statyczny::FORM_NAME, 'składany' => prawda, 'porządek sortowania' => 10, 'otwarte' => prawda, ], ], ], 'dzieci' => [ static::CONTAINER_HEADER_NAME => $this->getHeaderContainerConfig(10), static::FIELD_NAME_TEXT => $this->getTextFieldConfig(20), static::FIELD_NAME_SELECT => $this->getSelectFieldConfig(30), static::FIELD_NAME_MULTISELECT => $this->getMultiSelectFieldConfig(40), ], ]; } ?>
Dziedziczymy po abstrakcyjnym modyfikatorze formularza interfejsu użytkownika produktu i używamy jego przestrzeni nazw i danych jako dostawcy: 'provider' => static::DATA_SCOPE_PRODUCT . „_data_source” (gdzie DATA_SCOPE_PRODUCT to wiersz „data.product”).
Opcja componentType jest jedną z głównych opcji i odpowiada za typ komponentu. Opcja collapsible odpowiada za zwijanie i rozwijanie naszego zestawu pól. A opcja open określa, czy zestaw pól będzie domyślnie otwarty podczas rysowania formularza.
Następnie konsekwentnie dodajemy nagłówek do naszego zestawu pól w metodzie getHeaderContainerConfig oraz 3 przykłady pól: text, select i multiselect. Jednak nasz produkt i formularz nie otrzymają danych, dopóki nie dodamy ich do metody modyfikacjiData. Ale mamy możliwość przesyłania i przechwytywania danych podczas zapisywania.
Zobaczmy jak wygląda formularz:
Zapisywanie danych odbywa się w pliku kontrolera produktu vendor/magento/module-catalog/Controller/Adminhtml/Product/Save.php w głównej metodzie wykonywania. Jeśli wszystko zostało zrobione we właściwy sposób, to nasze dane będą poprawnie wyświetlane w danych wejściowych tej metody:
Pamiętaj, że jeśli Twój produkt nie ma tych atrybutów od początku, powinieneś zapisać je ręcznie. Możesz to zrobić w obserwatorze.
Najpierw zadeklaruj go w pliku app/code/Vendor/Product/etc/adminhtml/events.xml (używamy zakresu adminhtml, ponieważ formularz nie istnieje na interfejsie):
<?xml version="1.0"?> <config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> <event name="catalog_product_save_after"> <observer name="save_example_data" instance="Dostawca\Produkt\Obserwator\ProduktZapiszPo" /> </event> </config>
Następnie stwórz klasę obserwatora, którą wskazaliśmy w atrybucie instancji – app/code/Vendor/Product/Observer/ProductSaveAfter.php:
<?php przestrzeń nazw Dostawca\Produkt\Obserwator; użyj \Magento\Framework\Event\ObserverInterface; użyj \Magento\Framework\Event\Observer jako EventObserver; użyj Vendor\Product\Ui\DataProvider\Product\Form\Modifier\CustomFieldset; klasa ProduktZapiszPo wdrożeniu ObserverInterface { /** * @param EventObserver $observer */ wykonanie funkcji publicznej (\Magento\Framework\Event\Observer $observer) { /** @var \Magento\Katalog\Model\Produkt $produkt */ $product = $observer->getEvent()->getProduct(); jeśli (!$produkt) { zwrócić; } $exampleTextField = $product->getData(CustomFieldset::FIELD_NAME_TEXT); $exampleSelectField = $product->getData(CustomFieldset::FIELD_NAME_SELECT); $exampleMultiSelectField = $product->getData(CustomFieldset::FIELD_NAME_MULTISELECT); // Manipuluj danymi tutaj } } ?>
Dane w obserwatorze:
Teraz możesz wywołać własny model z obserwatora i zapisać w nim dane lub zmodyfikować go według własnego uznania.
Bądź ostrożny! Jeśli zapisanie Twojego modelu jest połączone z zapisywaniem produktu, może to prowadzić do rekursji.