Giải pháp trên không hoàn toàn chính xác. Bạn đang thêm một trường dưới dạng phần tử html "trần trụi" và biểu mẫu sản phẩm là biểu mẫu UI có đặc thù riêng. Một lớp đặc biệt ( vendor/magento/module-ui/view/base/web/js/form/form.js
) chịu trách nhiệm thu thập các trường và xác thực của chúng khi một biểu mẫu được gửi. Ngoài ra, lớp này nên bỏ lỡ các trường không liên quan đến biểu mẫu UI này hoặc không additional fields
giống như tất cả các trường của bạn. Bạn nên sử dụng cách đặt tên sau để đảm bảo rằng trường của bạn sẽ được gửi đến bộ điều khiển:
Nhưng điều này không hoàn toàn chính xác vì giải pháp chính xác là không đi chệch khỏi các tiêu chuẩn sử dụng mẫu UI và sử dụng các thành phần và thành phần gốc của nó. Trong trường hợp này, bạn không nên lo lắng về điều đó vì mọi thứ sẽ được xử lý tự động.
Như bạn có thể thấy từ mã này, một biểu mẫu html với tất cả các trường của nó không được gửi. Tuy nhiên, this.source
và this.additionalFields
được gửi nhưng phần tử của bạn không được bao gồm trong đó vì nó được khai báo không chính xác.
Dưới đây là ví dụ về cách thêm một bộ trường từ blog của chúng tôi. Bạn có thể đọc toàn bộ bài viết, sử dụng liên kết dưới đây:
Thêm nội dung: siêu dữ liệu dạng UI và loại ảo để bổ sung.
Tạo một tập tin app/code/Vendor/Product/etc/adminhtml/di.xml
. Chúng tôi sẽ đặt một sửa đổi bên trong:
<?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>
Bây giờ, tạo tệp sửa đổi ( app/code/Vendor/Product/Ui/DataProvider/Product/Form/Modifier/CustomFieldset.php
) với một bộ trường tùy chỉnh cho trang chỉnh sửa sản phẩm và điền nó vào các trường:
<?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;
}
}
Việc lưu dữ liệu diễn ra bên trong tệp bộ điều khiển sản phẩm
vendor/magento/module-catalog/Controller/Adminhtml/Product/Save.php
trong phương thức thực hiện chính. Nếu mọi thứ đã được thực hiện đúng cách, thì dữ liệu của chúng tôi sẽ được hiển thị chính xác trong dữ liệu đầu vào của phương pháp này:
Lưu ý, nếu sản phẩm của bạn không có các thuộc tính đó ngay từ đầu, bạn nên lưu chúng theo cách thủ công. Bạn có thể làm điều này trong người quan sát.
Đầu tiên, khai báo nó trong
app/code/Vendor/Product/etc/adminhtml/events.xml
tệp (chúng tôi đang sử dụng phạm vi adminhtml vì biểu mẫu không tồn tại ở mặt trước):
<?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>
Sau đó, tạo lớp của người quan sát mà chúng ta đã chỉ trong thuộc tính thể hiện - 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
}
}
Dữ liệu trong trình quan sát:
Bây giờ, bạn có thể gọi mô hình của riêng bạn từ người quan sát và lưu dữ liệu trong đó hoặc sửa đổi nó theo ý muốn.
Hãy cẩn thận! Nếu việc lưu mô hình của bạn được kết nối với việc tiết kiệm sản phẩm, thì nó có thể dẫn đến sự đệ quy.