La soluzione sopra non è completamente corretta. Stai aggiungendo un campo come elemento html "nudo" e un modulo di prodotto è un modulo di interfaccia utente con le sue peculiarità. Una classe speciale ( vendor/magento/module-ui/view/base/web/js/form/form.js
) è responsabile della raccolta dei campi e della loro convalida quando viene inviato un modulo. Inoltre, questa classe dovrebbe perdere i campi che non sono correlati a questo modulo dell'interfaccia utente o che non sono additional fields
come tutti i campi. È necessario utilizzare la seguente denominazione per assicurarsi che il campo verrà inviato al controller:
Ma questo non è completamente corretto perché la soluzione corretta non è quella di deviare dagli standard di utilizzo del modulo dell'interfaccia utente e utilizzare i suoi elementi e componenti nativi. In questo caso non dovresti preoccuparti di una cosa del genere perché tutto verrà elaborato automaticamente.
È possibile verificare il metodo principale di archiviazione dei dati dei moduli dell'interfaccia utente per comprendere il processo:
Come puoi vedere da questo codice, non viene inviato un modulo HTML con tutti i suoi campi. Tuttavia, this.source
e this.additionalFields
stanno inviare, ma il vostro elemento non è incluso in essa, perché è dichiarato in modo non corretto.
Ecco l'esempio su come aggiungere un fieldset dal nostro blog. Puoi leggere l'articolo completo, usando il link seguente:
Aggiungi il contenuto: i metadati del modulo UI e il tipo virtuale per la sua aggiunta.
Crea un file app/code/Vendor/Product/etc/adminhtml/di.xml
. Inseriremo un modificatore all'interno:
<?xml version="1.0"?>
<config xmlns:xsi="http://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">
<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>
</virtualType>
</config>
Ora crea il file modificatore ( app/code/Vendor/Product/Ui/DataProvider/Product/Form/Modifier/CustomFieldset.php
) con un set di campi personalizzato per la pagina di modifica del prodotto e riempilo con i campi:
<?php
namespace Vendor\Product\Ui\DataProvider\Product\Form\Modifier;
use Magento\Catalog\Model\Locator\LocatorInterface;
use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier;
use Magento\Framework\Stdlib\ArrayManager;
use Magento\Framework\UrlInterface;
use Magento\Ui\Component\Container;
use Magento\Ui\Component\Form\Fieldset;
use Magento\Ui\Component\Form\Element\DataType\Number;
use Magento\Ui\Component\Form\Element\DataType\Text;
use Magento\Ui\Component\Form\Element\Input;
use Magento\Ui\Component\Form\Element\Select;
use Magento\Ui\Component\Form\Element\MultiSelect;
use Magento\Ui\Component\Form\Field;
class CustomFieldset extends AbstractModifier
{
// Components indexes
const CUSTOM_FIELDSET_INDEX = 'custom_fieldset';
const CUSTOM_FIELDSET_CONTENT = 'custom_fieldset_content';
const CONTAINER_HEADER_NAME = 'custom_fieldset_content_header';
// Fields names
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
*/
protected $locator;
/**
* @var ArrayManager
*/
protected $arrayManager;
/**
* @var UrlInterface
*/
protected $urlBuilder;
/**
* @var array
*/
protected $meta = [];
/**
* @param LocatorInterface $locator
* @param ArrayManager $arrayManager
* @param UrlInterface $urlBuilder
*/
public function __construct(
LocatorInterface $locator,
ArrayManager $arrayManager,
UrlInterface $urlBuilder
) {
$this->locator = $locator;
$this->arrayManager = $arrayManager;
$this->urlBuilder = $urlBuilder;
}
/**
* Data modifier, does nothing in our example.
*
* @param array $data
* @return array
*/
public function modifyData(array $data)
{
return $data;
}
/**
* Meta-data modifier: adds ours fieldset
*
* @param array $meta
* @return array
*/
public function modifyMeta(array $meta)
{
$this->meta = $meta;
$this->addCustomFieldset();
return $this->meta;
}
/**
* Merge existing meta-data with our meta-data (do not overwrite it!)
*
* @return void
*/
protected function addCustomFieldset()
{
$this->meta = array_merge_recursive(
$this->meta,
[
static::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(),
]
);
}
/**
* Declare ours fieldset config
*
* @return array
*/
protected function getFieldsetConfig()
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Fieldset Title'),
'componentType' => Fieldset::NAME,
'dataScope' => static::DATA_SCOPE_PRODUCT, // save data in the product data
'provider' => static::DATA_SCOPE_PRODUCT . '_data_source',
'ns' => static::FORM_NAME,
'collapsible' => true,
'sortOrder' => 10,
'opened' => true,
],
],
],
'children' => [
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),
],
];
}
/**
* Get config for header container
*
* @param int $sortOrder
* @return array
*/
protected function getHeaderContainerConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => null,
'formElement' => Container::NAME,
'componentType' => Container::NAME,
'template' => 'ui/form/components/complex',
'sortOrder' => $sortOrder,
'content' => __('You can write any text here'),
],
],
],
'children' => [],
];
}
/**
* Example text field config
*
* @param $sortOrder
* @return array
*/
protected function getTextFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Example Text Field'),
'formElement' => Field::NAME,
'componentType' => Input::NAME,
'dataScope' => static::FIELD_NAME_TEXT,
'dataType' => Number::NAME,
'sortOrder' => $sortOrder,
],
],
],
];
}
/**
* Example select field config
*
* @param $sortOrder
* @return array
*/
protected function getSelectFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Options Select'),
'componentType' => Field::NAME,
'formElement' => Select::NAME,
'dataScope' => static::FIELD_NAME_SELECT,
'dataType' => Text::NAME,
'sortOrder' => $sortOrder,
'options' => $this->_getOptions(),
'visible' => true,
'disabled' => false,
],
],
],
];
}
/**
* Example multi-select field config
*
* @param $sortOrder
* @return array
*/
protected function getMultiSelectFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Options Multiselect'),
'componentType' => Field::NAME,
'formElement' => MultiSelect::NAME,
'dataScope' => static::FIELD_NAME_MULTISELECT,
'dataType' => Text::NAME,
'sortOrder' => $sortOrder,
'options' => $this->_getOptions(),
'visible' => true,
'disabled' => false,
],
],
],
];
}
/**
* Get example options as an option array:
* [
* label => string,
* value => option_id
* ]
*
* @return array
*/
protected function _getOptions()
{
$options = [
1 => [
'label' => __('Option 1'),
'value' => 1
],
2 => [
'label' => __('Option 2'),
'value' => 2
],
3 => [
'label' => __('Option 3'),
'value' => 3
],
];
return $options;
}
}
Il salvataggio dei dati avviene all'interno del file del controller del prodotto
vendor/magento/module-catalog/Controller/Adminhtml/Product/Save.php
nel metodo di esecuzione principale. Se tutto è stato fatto nel modo giusto, i nostri dati verranno visualizzati correttamente nei dati di input di questo metodo:
Nota, se il tuo prodotto non ha questi attributi dall'inizio, dovresti salvarli manualmente. Puoi farlo nell'osservatore.
Per prima cosa, dichiaralo nel
app/code/Vendor/Product/etc/adminhtml/events.xml
file (stiamo usando l'ambito adminhtml perché il modulo non esiste sul front-end):
<?xml version="1.0"?>
<config xmlns:xsi="http://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" />
</event>
</config>
Quindi, crea la classe dell'osservatore che abbiamo indicato nell'attributo dell'istanza - app/code/Vendor/Product/Observer/ProductSaveAfter.php
:
<?php
namespace Vendor\Product\Observer;
use \Magento\Framework\Event\ObserverInterface;
use \Magento\Framework\Event\Observer as EventObserver;
use Vendor\Product\Ui\DataProvider\Product\Form\Modifier\CustomFieldset;
class ProductSaveAfter implements ObserverInterface
{
/**
* @param EventObserver $observer
*/
public function execute(\Magento\Framework\Event\Observer $observer)
{
/** @var \Magento\Catalog\Model\Product $product */
$product = $observer->getEvent()->getProduct();
if (!$product) {
return;
}
$exampleTextField = $product->getData(CustomFieldset::FIELD_NAME_TEXT);
$exampleSelectField = $product->getData(CustomFieldset::FIELD_NAME_SELECT);
$exampleMultiSelectField = $product->getData(CustomFieldset::FIELD_NAME_MULTISELECT);
// Manipulate data here
}
}
I dati nell'osservatore:
Ora puoi chiamare il tuo modello dall'osservatore e salvare i dati al suo interno o modificarlo come desideri.
Stai attento! Se il salvataggio del tuo modello è collegato al salvataggio del prodotto, può portare alla ricorsione.