วิธีการแก้ปัญหาข้างต้นไม่ถูกต้องอย่างสมบูรณ์ คุณกำลังเพิ่มเขตข้อมูลเป็นองค์ประกอบ html "เปล่า" และรูปแบบผลิตภัณฑ์เป็นรูปแบบ UI ที่มีลักษณะเฉพาะของตัวเอง คลาสพิเศษ ( vendor/magento/module-ui/view/base/web/js/form/form.js
) รับผิดชอบการรวบรวมฟิลด์และการตรวจสอบความถูกต้องเมื่อส่งแบบฟอร์ม นอกจากนี้คลาสนี้ควรพลาดฟิลด์ที่ไม่เกี่ยวข้องกับฟอร์ม UI นี้หรือไม่additional fields
เหมือนกับฟิลด์ทั้งหมดของคุณ คุณควรใช้การตั้งชื่อต่อไปนี้เพื่อให้แน่ใจว่าเขตข้อมูลของคุณจะถูกส่งไปยังตัวควบคุม:
แต่สิ่งนี้ไม่ถูกต้องอย่างสมบูรณ์เพราะโซลูชันที่ถูกต้องไม่เบี่ยงเบนไปจากมาตรฐานการใช้งานรูปแบบ UI และใช้องค์ประกอบและส่วนประกอบดั้งเดิม ในกรณีนี้คุณไม่ควรกังวลเกี่ยวกับสิ่งนี้เพราะทุกอย่างจะถูกดำเนินการโดยอัตโนมัติ
คุณสามารถตรวจสอบวิธีการหลักในการจัดเก็บข้อมูลแบบฟอร์ม UI เพื่อทำความเข้าใจกระบวนการ:
นี่คือตัวอย่างเกี่ยวกับวิธีเพิ่ม fieldset จากบล็อกของเรา คุณสามารถอ่านบทความเต็มโดยใช้ลิงค์ด้านล่าง:
เพิ่มเนื้อหา: เมตาดาต้ารูปแบบ UI และประเภทเสมือนสำหรับการเพิ่ม
app/code/Vendor/Product/etc/adminhtml/di.xml
สร้างไฟล์ เราจะวางโมดิฟายเออร์ภายใน:
<?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>
ตอนนี้ให้สร้างไฟล์ตัวดัดแปลง ( app/code/Vendor/Product/Ui/DataProvider/Product/Form/Modifier/CustomFieldset.php
) ด้วยชุดฟิลด์ที่กำหนดเองสำหรับหน้าแก้ไขผลิตภัณฑ์และเติมด้วยฟิลด์:
<?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;
}
}
การบันทึกข้อมูลจะเกิดขึ้นภายในไฟล์คอนโทรลเลอร์ของผลิตภัณฑ์
vendor/magento/module-catalog/Controller/Adminhtml/Product/Save.php
ในวิธีดำเนินการหลัก หากทุกอย่างถูกต้องแล้วข้อมูลของเราจะแสดงอย่างถูกต้องในข้อมูลอินพุตของวิธีนี้:
หมายเหตุหากผลิตภัณฑ์ของคุณไม่มีคุณลักษณะเหล่านั้นตั้งแต่ต้นคุณควรบันทึกด้วยตนเอง คุณสามารถทำได้ในผู้สังเกตการณ์
ก่อนอื่นให้ประกาศใน
app/code/Vendor/Product/etc/adminhtml/events.xml
ไฟล์ (เรากำลังใช้ขอบเขต adminhtml เพราะแบบฟอร์มไม่มีอยู่ในส่วนหน้า):
<?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>
จากนั้นสร้างคลาสของผู้สังเกตการณ์ที่เราชี้ไปที่แอตทริบิวต์ของอินสแตนซ์ - 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
}
}
ข้อมูลในผู้สังเกตการณ์:
ตอนนี้คุณสามารถเรียกรุ่นของคุณเองจากผู้สังเกตการณ์และบันทึกข้อมูลไว้ในนั้นหรือแก้ไขตามที่คุณต้องการ
ระวัง! หากการบันทึกแบบจำลองของคุณเชื่อมต่อกับการบันทึกผลิตภัณฑ์อาจทำให้เกิดการเรียกซ้ำ