Moyen facile d'ajouter un ensemble de champs avec des champs au formulaire d'interface utilisateur
Publié: 2016-08-23Dans cet article, nous allons créer un module simple qui ajoutera un ensemble de champs avec des champs dans le formulaire d'interface utilisateur d'édition du produit. Aussi, nous allons créer un observateur pour intercepter ces données lors de la sauvegarde du produit.
Premièrement, nous devons créer un module Vendor_Product :
1. Créez un répertoire app/code/Vendor/Product
2. Créez un fichier d'enregistrement app/code/Vendor/Product/registration.php avec le contenu suivant :
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Fournisseur_Produit', __DIR__ ); ?>
Créez un fichier composer (si vous envisagez de transférer le module) app/code/Vendor/Module/composer.json :
{ "name": "fournisseur/module-produit", "description": "N/A", "type": "magento2-module", "version": "1.0.0", "Licence": [ "OSL-3.0", "AFL-3.0" ], "chargement automatique": { "des dossiers": [ "inscription.php" ], "psr-4": { "Fournisseur\\Produit\\": "" } } }
Maintenant, créez le fichier XML principal du module app/code/Vendor/Product/etc/module.xml avec la dépendance du module Magento_Catalog car notre fenêtre modale sera ajoutée à son formulaire :
<?xml version="1.0"?> <config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <nom du module="Vendor_Product" setup_version="1.0.0"> <séquence> <nom du module="Magento_Catalog"/> </séquence> </module> </config>
Activez le module en saisissant ce qui suit : bin/magento module:enable Vendor_Product et bin/magento setup:upgrade dans le répertoire racine de Magento.
Ensuite, ajoutez le contenu du module : les métadonnées du formulaire d'interface utilisateur et le type virtuel pour son ajout.
Créez un fichier app/code/Vendor/Product/etc/adminhtml/di.xml. Nous allons placer un modificateur à l'intérieur :
<?xml version="1.0"?> <config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <nom du type virtuel="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool"> <arguments> <argument name="modifiers" 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> </ arguments> </typevirtuel> </config>
Le modificateur est responsable de l'ajout de données et de certaines manipulations avec des éléments et des composants de formulaire d'interface utilisateur. Il existe 2 méthodes principales issues de l'interface du modificateur (elles doivent toujours être présentes) :
<?php /** * Copyright 2016 Magento. Tous les droits sont réservés. * Voir COPYING.txt pour les détails de la licence. */ espace de noms Magento\Ui\DataProvider\Modifier ; /** * Modificateur de classeInterface */ interface ModificateurInterface { /** * @param tableau $data * tableau @return */ fonction publique modifieDonnées(tableau $données); /** * tableau @param $meta * tableau @return */ fonction publique modifyMeta(tableau $meta); } ?>
Nous allons utiliser la méthode modifyMeta dans cet exemple. La méthode modifyData sera expliquée dans le prochain article.
Maintenant, créez le fichier de modification (app/code/Vendor/Product/Ui/DataProvider/Product/Form/Modifier/CustomFieldset.php) avec un ensemble de champs personnalisés pour la page d'édition du produit et remplissez-le avec les champs :
<?php espace de noms Vendor\Product\Ui\DataProvider\Product\Form\Modifier ; utilisez Magento\Catalog\Model\Locator\LocatorInterface ; utilisez Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier ; utilisez Magento\Framework\Stdlib\ArrayManager ; utilisez Magento\Framework\UrlInterface ; utilisez Magento\Ui\Component\Container ; utilisez Magento\Ui\Component\Form\Fieldset ; utilisez Magento\Ui\Component\Form\Element\DataType\Number ; utilisez Magento\Ui\Component\Form\Element\DataType\Text ; utilisez Magento\Ui\Component\Form\Element\Input ; utilisez Magento\Ui\Component\Form\Element\Select ; utilisez Magento\Ui\Component\Form\Element\MultiSelect ; utilisez Magento\Ui\Component\Form\Field ; la classe CustomFieldset étend AbstractModifier { // Index des composants const CUSTOM_FIELDSET_INDEX = 'custom_fieldset' ; const CUSTOM_FIELDSET_CONTENT = 'custom_fieldset_content' ; const CONTAINER_HEADER_NAME = 'custom_fieldset_content_header' ; // Noms des champs 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 */ localisateur $ protégé ; /** * @var ArrayManager */ protégé $arrayManager ; /** * @var InterfaceUrl */ $urlBuilder protégé ; /** * Tableau @var */ protégé $meta = [] ; /** * @param LocatorInterface $locator * @param ArrayManager $arrayManager * @param UrlInterface $urlBuilder */ fonction publique __construct( LocalisateurInterface $localisateur, ArrayManager $arrayManager, UrlInterface $urlBuilder ) { $this->locator = $locator; $this->arrayManager = $arrayManager; $this->urlBuilder = $urlBuilder ; } /** * Modificateur de données, ne fait rien dans notre exemple. * * @param tableau $data * tableau @return */ fonction publique modifieDonnées(tableau $données) { retourne $données ; } /** * Modificateur de métadonnées : ajoute le nôtre ensemble de champs * * tableau @param $meta * tableau @return */ fonction publique modifyMeta(tableau $meta) { $this->meta = $meta; $this->addCustomFieldset(); retourne $this->meta ; } /** * Fusionnez les métadonnées existantes avec nos métadonnées (ne les écrasez pas !) * * @retour vide */ fonction protégée addCustomFieldset() { $this->meta = array_merge_recursive( $this->meta, [ static::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(), ] ); } /** * Déclarez notre configuration de champs * * tableau @return */ fonction protégée getFieldsetConfig() { revenir [ 'arguments' => [ 'données' => [ 'config' => [ 'label' => __('Titre du champ'), 'componentType' => Fieldset ::NOM, 'dataScope' => static::DATA_SCOPE_PRODUCT, // enregistre les données dans les données produit 'fournisseur' => static::DATA_SCOPE_PRODUCT . '_la source de données', 'ns' => statique::FORM_NAME, 'réductible' => vrai, 'sortOrder' => 10, 'ouvert' => vrai, ], ], ], 'enfants' => [ static::CONTAINER_HEADER_NAME => $this->getHeaderContainerConfig(10), statique :: FIELD_NAME_TEXT => $this->getTextFieldConfig(20), static::FIELD_NAME_SELECT => $this->getSelectFieldConfig(30), static::FIELD_NAME_MULTISELECT => $this->getMultiSelectFieldConfig(40), ], ] ; } /** * Obtenir la configuration du conteneur d'en-tête * * @param entier $sortOrder * tableau @return */ fonction protégée getHeaderContainerConfig($sortOrder) { revenir [ 'arguments' => [ 'données' => [ 'config' => [ 'étiquette' => null, 'formElement' => Conteneur :: NOM, 'componentType' => Conteneur :: NOM, 'template' => 'ui/formulaire/composants/complexe', 'sortOrder' => $sortOrder, 'content' => __('Vous pouvez écrire n'importe quel texte ici'), ], ], ], 'enfants' => [], ] ; } /** * Exemple de configuration de champ de texte * * @param $sortOrder * tableau @return */ fonction protégée getTextFieldConfig($sortOrder) { revenir [ 'arguments' => [ 'données' => [ 'config' => [ 'label' => __('Exemple de champ de texte'), 'formElement' => Champ :: NOM, 'componentType' => Entrée :: NOM, 'dataScope' => statique :: FIELD_NAME_TEXT, 'dataType' => Numéro :: NOM, 'sortOrder' => $sortOrder, ], ], ], ] ; } /** * Exemple de configuration de champ de sélection * * @param $sortOrder * tableau @return */ fonction protégée getSelectFieldConfig($sortOrder) { revenir [ 'arguments' => [ 'données' => [ 'config' => [ 'label' => __('Options Select'), 'componentType' => Champ :: NOM, 'formElement' => Select::NOM, 'dataScope' => statique :: FIELD_NAME_SELECT, 'dataType' => Texte :: NOM, 'sortOrder' => $sortOrder, 'options' => $this->_getOptions(), 'visible' => vrai, 'désactivé' => faux, ], ], ], ] ; } /** * Exemple de configuration de champ à sélection multiple * * @param $sortOrder * tableau @return */ fonction protégée getMultiSelectFieldConfig($sortOrder) { revenir [ 'arguments' => [ 'données' => [ 'config' => [ 'label' => __('Options sélection multiple'), 'componentType' => Champ :: NOM, 'formElement' => MultiSelect::NOM, 'dataScope' => statique :: FIELD_NAME_MULTISELECT, 'dataType' => Texte :: NOM, 'sortOrder' => $sortOrder, 'options' => $this->_getOptions(), 'visible' => vrai, 'désactivé' => faux, ], ], ], ] ; } /** * Obtenez des exemples d'options sous forme de tableau d'options : * [ * étiquette => chaîne, * valeur => option_id * ] * * tableau @return */ fonction protégée _getOptions() { $options = [ 1 => [ 'étiquette' => __('Option 1'), 'valeur' => 1 ], 2 => [ 'étiquette' => __('Option 2'), 'valeur' => 2 ], 3 => [ 'étiquette' => __('Option 3'), 'valeur' => 3 ], ] ; retourner $options ; } } ?>
Dans cet exemple, nous devons prendre les métadonnées existantes du formulaire d'interface utilisateur et les fusionner (et non les réécrire !) avec nos nouvelles données :
<?php /** * Fusionnez les métadonnées existantes avec nos métadonnées (ne les écrasez pas !) * * @retour vide */ fonction protégée addCustomFieldset() { $this->meta = array_merge_recursive( $this->meta, [ static::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(), ] ); } ?>
Une fois terminé, ajoutez le nouveau jeu de champs à la méthode getFieldsetConfig :
<?php /** * Déclarez notre configuration de champs * * tableau @return */ fonction protégée getFieldsetConfig() { revenir [ 'arguments' => [ 'données' => [ 'config' => [ 'label' => __('Titre du champ'), 'componentType' => Fieldset ::NOM, 'dataScope' => static::DATA_SCOPE_PRODUCT, // enregistre les données dans les données produit 'fournisseur' => static::DATA_SCOPE_PRODUCT . '_la source de données', 'ns' => statique::FORM_NAME, 'réductible' => vrai, 'sortOrder' => 10, 'ouvert' => vrai, ], ], ], 'enfants' => [ static::CONTAINER_HEADER_NAME => $this->getHeaderContainerConfig(10), statique :: FIELD_NAME_TEXT => $this->getTextFieldConfig(20), static::FIELD_NAME_SELECT => $this->getSelectFieldConfig(30), static::FIELD_NAME_MULTISELECT => $this->getMultiSelectFieldConfig(40), ], ] ; } ?>
Nous héritons du modificateur abstract product UI-form et utilisons son espace de noms et ses données comme fournisseur : 'provider' => static::DATA_SCOPE_PRODUCT . '_data_source' (où DATA_SCOPE_PRODUCT est la ligne 'data.product').
L'option componentType est l'une des options principales et est responsable du type de composant. L'option pliable est responsable de l'effondrement et de l'expansion de notre ensemble de champs. Et l'option d'ouverture définit si le jeu de champs sera ouvert par défaut lors du dessin du formulaire.
Ensuite, nous ajoutons par conséquent un en-tête à notre fieldset dans la méthode getHeaderContainerConfig et 3 exemples de champs : text, select et multiselect. Cependant, notre produit et notre formulaire ne recevront pas de données tant que nous ne les ajouterons pas à la méthode modifyData. Mais nous avons la capacité de transmettre et d'intercepter les données lors de la sauvegarde.
Voyons à quoi ressemble le formulaire :
La sauvegarde des données a lieu dans le fichier du contrôleur de produit vendor/magento/module-catalog/Controller/Adminhtml/Product/Save.php dans la méthode d'exécution principale. Si tout a été fait de la bonne manière, alors nos données s'afficheront correctement dans les données d'entrée de cette méthode :
Notez que si votre produit ne possède pas ces attributs depuis le début, vous devez les enregistrer manuellement. Vous pouvez le faire dans l'observateur.
Tout d'abord, déclarez-le dans le fichier app/code/Vendor/Product/etc/adminhtml/events.xml (nous utilisons la portée adminhtml car le formulaire n'existe pas sur le front-end) :
<?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="Vendor\Product\Observer\ProductSaveAfter" /> </événement> </config>
Ensuite, créez la classe de l'observateur que nous avons pointée dans l'attribut d'instance - app/code/Vendor/Product/Observer/ProductSaveAfter.php :
<?php espace de noms Vendor\Product\Observer ; utilisez \Magento\Framework\Event\ObserverInterface ; utilisez \Magento\Framework\Event\Observer comme EventObserver ; utilisez Vendor\Product\Ui\DataProvider\Product\Form\Modifier\CustomFieldset ; la classe ProductSaveAfter implémente ObserverInterface { /** * @param EventObserver $observateur */ fonction publique execute(\Magento\Framework\Event\Observer $observer) { /** @var \Magento\Catalog\Model\Product $product */ $product = $observer->getEvent()->getProduct(); si (!$produit) { revenir; } $exampleTextField = $product->getData(CustomFieldset ::FIELD_NAME_TEXT); $exampleSelectField = $product->getData(CustomFieldset ::FIELD_NAME_SELECT); $exampleMultiSelectField = $product->getData(CustomFieldset ::FIELD_NAME_MULTISELECT); // Manipuler les données ici } } ?>
Les données dans l'observateur :
Maintenant, vous pouvez appeler votre propre modèle à partir de l'observateur et y enregistrer des données ou les modifier à votre guise.
Faire attention! Si la sauvegarde de votre modèle est liée à la sauvegarde du produit, cela peut entraîner la récursivité.