Ł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.
