Einfache Möglichkeit, ein Fieldset mit Feldern zum UI-Formular hinzuzufügen

Veröffentlicht: 2016-08-23

In diesem Artikel erstellen wir ein einfaches Modul, das ein Fieldset mit Feldern im UI-Formular zur Produktbearbeitung hinzufügt. Außerdem werden wir einen Beobachter erstellen, der diese Daten während der Produktspeicherung abfängt.

Zuerst müssen wir ein Vendor_Product-Modul erstellen:

1. Erstellen Sie ein Verzeichnis app/code/Vendor/Product
2. Erstellen Sie eine Registrierungsdatei app/code/Vendor/Product/registration.php mit folgendem Inhalt:

 <?php
    \Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE,
        'Lieferant_Produkt',
        __DIR__
    );
    ?>

Erstellen Sie eine Composer-Datei (wenn Sie das Modul übertragen möchten) app/code/Vendor/Module/composer.json :

 {
        "name": "Anbieter/Modul-Produkt",
        "Beschreibung": "Nicht zutreffend",
        "type": "magento2-modul",
        "Version": "1.0.0",
        "Lizenz": [
            "OSL-3.0",
            "AFL-3.0"
        ],
        "automatisches Laden": {
            "Dateien": [
                "registrierung.php"
            ],
            "psr-4": {
                "Anbieter\\Produkt\\": ""
            }
        }
    }

Erstellen Sie nun die Haupt-XML-Datei des Moduls app/code/Vendor/Product/etc/module.xml mit der Abhängigkeit vom Magento_Catalog-Modul, da unser modales Fenster zu seinem Formular hinzugefügt wird:

 <?xml-Version="1.0"?>
    <config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
        <Modulname="Vendor_Product" setup_version="1.0.0">
            <Sequenz>
                <Modulname="Magento_Catalog"/>
            </sequenz>
        </modul>
    </config>

Aktivieren Sie das Modul, indem Sie Folgendes eingeben: bin/magento module:enable Vendor_Product und bin/magento setup:upgrade im Stammverzeichnis von Magento.

Fügen Sie dann den Inhalt des Moduls hinzu: die Metadaten des UI-Formulars und den virtuellen Typ für seine Hinzufügung.

Erstellen Sie eine Datei app/code/Vendor/Product/etc/adminhtml/di.xml. Wir werden einen Modifikator darin platzieren:

 <?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">
        <Argumente>
            <argument name="modifikatoren" xsi:type="array">
                <item name="custom-fieldset" xsi:type="array">
                    <item name="class" xsi:type="string">Vendor\Product\Ui\DataProvider\Product\Form\Modifier\CustomFieldset</item>
                    <item name="sortOrder" xsi:type="number">10</item>
                </item>
            </Argument>
        </Argumente>
    </virtuellerTyp>
</config>

Der Modifikator ist für das Hinzufügen von Daten und einige Manipulationen mit Elementen und UI-Formularkomponenten verantwortlich. Es gibt 2 Hauptmethoden, die von der Schnittstelle des Modifikators stammen (sie sollten immer vorhanden sein):

 <?php
    /**
     * Urheberrecht 2016 Magento. Alle Rechte vorbehalten.
     * Siehe COPYING.txt für Lizenzdetails.
     */
    Namensraum Magento\Ui\DataProvider\Modifier;
    
    /**
     * Klasse ModifierInterface
     */
    Schnittstelle ModifierInterface
    {
        /**
         * @param-Array $data
         * @return-Array
         */
        öffentliche Funktion modifyData(array $data);
    
        /**
         * @param-Array $meta
         * @return-Array
         */
        öffentliche Funktion modifyMeta(array $meta);
    }
    ?>

In diesem Beispiel verwenden wir die Methode modifyMeta. Die Methode modifyData wird im nächsten Artikel erklärt.

Erstellen Sie nun die Modifikatordatei (app/code/Vendor/Product/Ui/DataProvider/Product/Form/Modifier/CustomFieldset.php) mit einem benutzerdefinierten Feldsatz für die Produktbearbeitungsseite und füllen Sie sie mit den Feldern:

 <?php
Namespace Vendor\Product\Ui\DataProvider\Product\Form\Modifier;

verwenden Sie Magento\Catalog\Model\Locator\LocatorInterface;
verwenden Sie Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier;
verwenden Sie Magento\Framework\Stdlib\ArrayManager;
verwenden Sie Magento\Framework\UrlInterface;
Verwenden Sie Magento\Ui\Component\Container;
Verwenden Sie Magento\Ui\Component\Form\Fieldset;
Verwenden Sie Magento\Ui\Component\Form\Element\DataType\Number;
Verwenden Sie Magento\Ui\Component\Form\Element\DataType\Text;
Verwenden Sie Magento\Ui\Component\Form\Element\Input;
Verwenden Sie Magento\Ui\Component\Form\Element\Select;
Verwenden Sie Magento\Ui\Component\Form\Element\MultiSelect;
Verwenden Sie Magento\Ui\Component\Form\Field;

Klasse CustomFieldset erweitert AbstractModifier
{

    // Komponentenindizes
    const CUSTOM_FIELDSET_INDEX = 'custom_fieldset';
    const CUSTOM_FIELDSET_CONTENT = 'custom_fieldset_content';
    const CONTAINER_HEADER_NAME = 'custom_fieldset_content_header';

    // Feldnamen
    const FIELD_NAME_TEXT = 'example_text_field';
    const FIELD_NAME_SELECT = 'example_select_field';
    const FIELD_NAME_MULTISELECT = 'example_multiselect_field';

    /**
     * @var \Magento\Catalog\Model\Locator\LocatorInterface
     */
    geschützter $locator;

    /**
     * @var ArrayManager
     */
    geschützt $arrayManager;

    /**
     * @var UrlInterface
     */
    geschützter $urlBuilder;

    /**
     * @var-Array
     */
    geschützt $meta = [];

    /**
     * @param LocatorInterface $locator
     * @param ArrayManager $ArrayManager
     * @param UrlInterface $urlBuilder
     */
    öffentliche Funktion __construct(
        LocatorInterface $locator,
        ArrayManager $ArrayManager,
        UrlInterface $urlBuilder
    ) {
        $this->locator = $locator;
        $this->arrayManager = $arrayManager;
        $this->urlBuilder = $urlBuilder;
    }

    /**
     * Datenmodifikator, macht in unserem Beispiel nichts.
     *
     * @param-Array $data
     * @return-Array
     */
    öffentliche Funktion modifyData(array $data)
    {
        $daten zurückgeben;
    }

    /**
     * Metadaten-Modifikator: Fügt unser Feldset hinzu
     *
     * @param-Array $meta
     * @return-Array
     */
    Öffentliche Funktion modifyMeta (array $meta)
    {
        $dies->meta = $meta;
        $this->addCustomFieldset();

        $this->meta zurückgeben;
    }

    /**
     * Vorhandene Metadaten mit unseren Metadaten zusammenführen (nicht überschreiben!)
     *
     * @return void
     */
    geschützte Funktion addCustomFieldset()
    {
        $this->meta = array_merge_recursive(
            $this->meta,
            [
                static::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(),
            ]
        );
    }

    /**
     * Deklarieren Sie unsere Fieldset-Konfiguration
     *
     * @return-Array
     */
    geschützte Funktion getFieldsetConfig()
    {
        Rückkehr [
            'Argumente' => [
                'Daten' => [
                    'config' => [
                        'label' => __('Feldsatztitel'),
                        'componentType' => Feldsatz::NAME,
                        'dataScope' => static::DATA_SCOPE_PRODUCT, // Daten in den Produktdaten speichern
                        'provider' => static::DATA_SCOPE_PRODUCT . '_Datenquelle',
                        'ns' => statisch::FORM_NAME,
                        'zusammenklappbar' => wahr,
                        'sortOrder' => 10,
                        'geöffnet' => wahr,
                    ],
                ],
            ],
            'Kinder' => [
                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),
            ],
        ];
    }

    /**
     * Holen Sie sich die Konfiguration für den Header-Container
     *
     * @param int $sortOrder
     * @return-Array
     */
    geschützte Funktion getHeaderContainerConfig($sortOrder)
    {
        Rückkehr [
            'Argumente' => [
                'Daten' => [
                    'config' => [
                        'label' => null,
                        'formElement' => Container::NAME,
                        'componentType' => Container::NAME,
                        'template' => 'ui/form/components/complex',
                        'sortOrder' => $sortOrder,
                        'content' => __('Du kannst hier einen beliebigen Text schreiben'),
                    ],
                ],
            ],
            'Kinder' => [],
        ];
    }

    /**
     * Beispiel Textfeldkonfiguration
     *
     * @param $sortOrder
     * @return-Array
     */
    geschützte Funktion getTextFieldConfig($sortOrder)
    {
        Rückkehr [
            'Argumente' => [
                'Daten' => [
                    'config' => [
                        'label' => __('Beispieltextfeld'),
                        'formElement' => Feld::NAME,
                        'Komponententyp' => Eingabe::NAME,
                        'dataScope' => static::FIELD_NAME_TEXT,
                        'dataType' => Zahl::NAME,
                        'sortOrder' => $sortOrder,
                    ],
                ],
            ],
        ];
    }

    /**
     * Beispiel Auswahlfeldkonfiguration
     *
     * @param $sortOrder
     * @return-Array
     */
    geschützte Funktion getSelectFieldConfig($sortOrder)
    {
        Rückkehr [
            'Argumente' => [
                'Daten' => [
                    'config' => [
                        'label' => __('Optionen auswählen'),
                        'componentType' => Feld::NAME,
                        'formElement' => Auswählen::NAME,
                        'dataScope' => static::FIELD_NAME_SELECT,
                        'dataType' => Text::NAME,
                        'sortOrder' => $sortOrder,
                        'Optionen' => $this->_getOptions(),
                        'sichtbar' => wahr,
                        'deaktiviert' => falsch,
                    ],
                ],
            ],
        ];
    }

    /**
     * Beispiel für Mehrfachauswahlfeldkonfiguration
     *
     * @param $sortOrder
     * @return-Array
     */
    geschützte Funktion getMultiSelectFieldConfig($sortOrder)
    {
        Rückkehr [
            'Argumente' => [
                'Daten' => [
                    'config' => [
                        'label' => __('Optionen Mehrfachauswahl'),
                        'componentType' => Feld::NAME,
                        'formElement' => MultiSelect::NAME,
                        'dataScope' => static::FIELD_NAME_MULTISELECT,
                        'dataType' => Text::NAME,
                        'sortOrder' => $sortOrder,
                        'Optionen' => $this->_getOptions(),
                        'sichtbar' => wahr,
                        'deaktiviert' => falsch,
                    ],
                ],
            ],
        ];
    }

    /**
     * Beispieloptionen als Optionsarray abrufen:
     * [
     * Bezeichnung => Zeichenkette,
     * Wert => Options-ID
     * ]
     *
     * @return-Array
     */
    geschützte Funktion _getOptions()
    {
        $optionen = [
            1 => [
                'label' => __('Option 1'),
                'Wert' => 1
            ],
            2 => [
                'label' => __('Option 2'),
                'Wert' => 2
            ],
            3 => [
                'label' => __('Option 3'),
                'Wert' => 3
            ],
        ];

        $optionen zurückgeben;
    }
}
?>

In diesem Beispiel müssen wir die vorhandenen Metadaten des UI-Formulars nehmen und sie mit unseren neuen Daten zusammenführen (nicht umschreiben!):

 <?php
/**
 * Vorhandene Metadaten mit unseren Metadaten zusammenführen (nicht überschreiben!)
 *
 * @return void
 */
geschützte Funktion addCustomFieldset()
{
    $this->meta = array_merge_recursive(
        $this->meta,
        [
            static::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(),
        ]
    );
}
?>

Wenn Sie fertig sind, fügen Sie das neue Fieldset zur Methode getFieldsetConfig hinzu:

 <?php
/**
 * Deklarieren Sie unsere Fieldset-Konfiguration
 *
 * @return-Array
 */
geschützte Funktion getFieldsetConfig()
{
    Rückkehr [
        'Argumente' => [
            'Daten' => [
                'config' => [
                    'label' => __('Feldsatztitel'),
                    'componentType' => Feldsatz::NAME,
                    'dataScope' => static::DATA_SCOPE_PRODUCT, // Daten in den Produktdaten speichern
                    'provider' => static::DATA_SCOPE_PRODUCT . '_Datenquelle',
                    'ns' => statisch::FORM_NAME,
                    'zusammenklappbar' => wahr,
                    'sortOrder' => 10,
                    'geöffnet' => wahr,
                ],
            ],
        ],
        'Kinder' => [
            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),
        ],
    ];
}
?>

Wir erben vom UI-Form-Modifizierer des abstrakten Produkts und verwenden seinen Namensraum und seine Daten als Anbieter: 'provider' => static::DATA_SCOPE_PRODUCT . '_data_source' (wobei DATA_SCOPE_PRODUCT die Zeile 'data.product' ist).

Die Option „componentType“ ist eine der Hauptoptionen und für den Komponententyp verantwortlich. Die zusammenklappbare Option ist für das Zusammenklappen und Erweitern unseres Feldsatzes verantwortlich. Und die Open-Option definiert, ob das Fieldset während des Formularzeichnens standardmäßig geöffnet ist.

Dann fügen wir unserem Fieldset konsequent einen Header in der getHeaderContainerConfig-Methode und 3 Beispiele für Felder hinzu: text, select und multiselect. Unser Produkt und unser Formular erhalten jedoch keine Daten, bis wir sie der modifyData-Methode hinzufügen. Wir haben aber die Möglichkeit, die Daten beim Speichern zu übermitteln und abzufangen.

Mal sehen, wie das Formular aussieht:

Die Datenspeicherung erfolgt in der Hauptausführungsmethode in der Produktcontrollerdateivendor/magento/module-catalog/Controller/Adminhtml/Product/Save.php. Wenn alles richtig gemacht wurde, werden unsere Daten in den Eingabedaten dieser Methode korrekt angezeigt:

Beachten Sie, wenn Ihr Produkt diese Attribute nicht von Anfang an hat, sollten Sie sie manuell speichern. Sie können dies im Beobachter tun.

Deklarieren Sie es zuerst in der Datei app/code/Vendor/Product/etc/adminhtml/events.xml (wir verwenden den Bereich adminhtml, da das Formular im Frontend nicht vorhanden ist):

 <?xml-Version="1.0"?>
<config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <Ereignisname="catalog_product_save_after">
        <observer name="save_example_data" instance="Vendor\Product\Observer\ProductSaveAfter" />
    </Ereignis>
</config>

Erstellen Sie dann die Klasse des Beobachters, auf die wir im Instanzattribut verwiesen haben – app/code/Vendor/Product/Observer/ProductSaveAfter.php:

 <?php
Namensraum Hersteller\Produkt\Beobachter;

Verwenden Sie \Magento\Framework\Event\ObserverInterface;
verwenden Sie \Magento\Framework\Event\Observer als EventObserver;
Verwenden Sie Vendor\Product\Ui\DataProvider\Product\Form\Modifier\CustomFieldset;

Die Klasse ProductSaveAfter implementiert ObserverInterface
{

    /**
     * @param EventObserver $Beobachter
     */
    öffentliche Funktion execute(\Magento\Framework\Event\Observer $observer)
    {
        /** @var \Magento\Catalog\Model\Product $product */
        $product = $observer->getEvent()->getProduct();
        if (!$produkt) {
            Rückkehr;
        }

        $exampleTextField = $product->getData(CustomFieldset::FIELD_NAME_TEXT);
        $exampleSelectField = $product->getData(CustomFieldset::FIELD_NAME_SELECT);
        $exampleMultiSelectField = $product->getData(CustomFieldset::FIELD_NAME_MULTISELECT);

        // Daten hier manipulieren
    }
}
?>

Die Daten im Beobachter:

Nun können Sie aus dem Observer Ihr eigenes Modell aufrufen und darin Daten speichern oder nach Belieben modifizieren.

Vorsichtig sein! Wenn die Speicherung Ihres Modells mit der Produktspeicherung verbunden ist, dann kann es zur Rekursion kommen.