วิธีง่ายๆ ในการเพิ่ม Fieldset พร้อมฟิลด์ใน UI-Form
เผยแพร่แล้ว: 2016-08-23ในบทความนี้ เราจะสร้างโมดูลอย่างง่ายที่จะเพิ่ม fieldset พร้อมฟิลด์ในแบบฟอร์ม UI การแก้ไขผลิตภัณฑ์ นอกจากนี้ เราจะสร้างผู้สังเกตการณ์เพื่อสกัดกั้นข้อมูลนี้ในระหว่างการบันทึกผลิตภัณฑ์
ขั้นแรก เราต้องสร้างโมดูล Vendor_Product:
1. สร้างไดเร็กทอรี app/code/Vendor/Product
2. สร้างไฟล์ลงทะเบียน app/code/Vendor/Product/registration.php โดยมีเนื้อหาดังนี้
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'ผู้ขาย_ผลิตภัณฑ์' __DIR__ ); ?>
สร้างไฟล์ผู้แต่ง (หากคุณวางแผนที่จะโอนโมดูล) app/code/Vendor/Module/composer.json :
{ "name": "ผู้จำหน่าย/โมดูล-ผลิตภัณฑ์", "description": "ไม่มี", "type": "magento2-module", "เวอร์ชัน": "1.0.0", "ใบอนุญาต": [ "OSL-3.0", "แอฟ-3.0" ], "โหลดอัตโนมัติ": { "ไฟล์": [ "การลงทะเบียน.php" ], "psr-4": { "ผู้ขาย\\Product\\": "" } } }
ตอนนี้ ให้สร้าง app/code/Vendor/Product/etc/module.xml ไฟล์ XML หลักของโมดูลด้วยการพึ่งพาจากโมดูล Magento_Catalog เนื่องจากหน้าต่างโมดอลของเราจะถูกเพิ่มลงในแบบฟอร์ม:
<?xml version="1.0"?> <config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Vendor_Product" setup_version="1.0.0"> <ลำดับ> <module name="Magento_Catalog"/> </sequence> </module> </config>
เปิดใช้งานโมดูลโดยป้อนข้อมูลต่อไปนี้: bin/magento module:enable Vendor_Product และ bin/magento setup:upgrade ในไดเร็กทอรี root Magento
จากนั้น เพิ่มเนื้อหาของโมดูล: meta-data ของฟอร์ม UI และประเภทเสมือนสำหรับการเพิ่ม
สร้างไฟล์ app/code/Vendor/Product/etc/adminhtml/di.xml. เราจะวางโมดิฟายเออร์ไว้ข้างใน:
<?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"> <อาร์กิวเมนต์> <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> </อาร์กิวเมนต์> </arguments> </virtualType> </config>
ตัวแก้ไขมีหน้าที่ในการเพิ่มข้อมูลและการปรับแต่งบางอย่างกับองค์ประกอบและส่วนประกอบรูปแบบ UI มี 2 วิธีหลักที่มาจากอินเทอร์เฟซของตัวปรับแต่ง (ควรมีอยู่เสมอ):
<?php /** * ลิขสิทธิ์ 2016 Magento สงวนลิขสิทธิ์. * ดู COPYING.txt สำหรับรายละเอียดใบอนุญาต */ เนมสเปซ Magento\Ui\DataProvider\Modifier; /** * Class ModifierInterface */ ตัวแก้ไขส่วนต่อประสานอินเทอร์เฟซ { /** * @param array $data * @return อาร์เรย์ */ ฟังก์ชั่นสาธารณะ modifiedData (อาร์เรย์ $ data); /** * @param array $meta * @return อาร์เรย์ */ ฟังก์ชั่นสาธารณะ modifiedMeta (อาร์เรย์ $ meta); } ?>
เราจะใช้เมธอด modifiedMeta ในตัวอย่างนี้ วิธี modifiedData จะอธิบายในบทความถัดไป
ตอนนี้ สร้างไฟล์ตัวแก้ไข (app/code/Vendor/Product/Ui/DataProvider/Product/Form/Modifier/CustomFieldset.php) ด้วย fieldset ที่กำหนดเองสำหรับหน้าแก้ไขผลิตภัณฑ์และกรอกข้อมูลด้วยฟิลด์:
<?php เนมสเปซ Vendor\Product\Ui\DataProvider\Product\Form\Modifier; ใช้ Magento\Catalog\Model\Locator\LocatorInterface; ใช้ Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; ใช้ Magento\Framework\Stdlib\ArrayManager; ใช้ Magento\Framework\UrlInterface; ใช้ Magento\Ui\Component\Container; ใช้ Magento\Ui\Component\Form\Fieldset; ใช้ Magento\Ui\Component\Form\Element\DataType\Number; ใช้ Magento\Ui\Component\Form\Element\DataType\Text; ใช้ Magento\Ui\Component\Form\Element\Input; ใช้ Magento\Ui\Component\Form\Element\Select; ใช้ Magento\Ui\Component\Form\Element\MultiSelect; ใช้ Magento\Ui\Component\Form\Field; คลาส CustomFieldset ขยาย AbstractModifier { // ดัชนีส่วนประกอบ const CUSTOM_FIELDSET_INDEX = 'custom_fieldset'; const CUSTOM_FIELDSET_CONTENT = 'custom_fieldset_content'; const CONTAINER_HEADER_NAME = 'custom_fieldset_content_header'; // ชื่อช่อง 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 */ ป้องกันตัวระบุตำแหน่ง $; /** * @var ArrayManager */ ป้องกัน $ arrayManager; /** * @var UrlInterface */ ป้องกัน $urlBuilder; /** * @var array */ ป้องกัน $meta = []; /** * @param LocatorInterface $locator * @param ArrayManager $arrayManager * @param UrlInterface $ urlBuilder */ ฟังก์ชั่นสาธารณะ __construct( LocatorInterface $ ตัวระบุตำแหน่ง, ArrayManager $arrayManager, UrlInterface $urlBuilder ) { $this->locator = $locator; $this->arrayManager = $arrayManager; $this->urlBuilder = $urlBuilder; } /** * ตัวแก้ไขข้อมูล ไม่ทำอะไรเลยในตัวอย่างของเรา * * @param array $data * @return อาร์เรย์ */ ฟังก์ชั่นสาธารณะ modifiedData (อาร์เรย์ $ data) { ส่งคืนข้อมูล $; } /** * ตัวแก้ไขข้อมูลเมตา: เพิ่ม fieldset ของเรา * * @param array $meta * @return อาร์เรย์ */ ฟังก์ชั่นสาธารณะ modifiedMeta (อาร์เรย์ $ meta) { $this->meta = $meta; $this->addCustomFieldset(); คืนค่า $this->meta; } /** * รวม meta-data ที่มีอยู่กับ meta-data ของเรา (อย่าเขียนทับ!) * * @return เป็นโมฆะ */ ฟังก์ชันที่ได้รับการป้องกัน addCustomFieldset() { $this->meta = array_merge_recursive( $this->เมตา, [ คงที่::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(), ] ); } /** * ประกาศ fieldset config . ของเรา * * @return อาร์เรย์ */ ฟังก์ชันที่ได้รับการป้องกัน getFieldsetConfig() { กลับ [ 'ข้อโต้แย้ง' => [ 'ข้อมูล' => [ 'config' => [ 'label' => __('ชื่อชุดฟิลด์'), 'componentType' => Fieldset::NAME, 'dataScope' => static::DATA_SCOPE_PRODUCT, // บันทึกข้อมูลใน data data 'provider' => static::DATA_SCOPE_PRODUCT . '_แหล่งข้อมูล', 'ns' => คงที่::FORM_NAME, 'พับได้' => จริง 'sortOrder' => 10, 'เปิด' => จริง ], ], ], 'ลูก' => [ คงที่::CONTAINER_HEADER_NAME => $this->getHeaderContainerConfig(10), คงที่::FIELD_NAME_TEXT => $this->getTextFieldConfig(20), คงที่::FIELD_NAME_SELECT => $this->getSelectFieldConfig(30), คงที่::FIELD_NAME_MULTISELECT => $this->getMultiSelectFieldConfig(40), ], ]; } /** * รับการกำหนดค่าสำหรับคอนเทนเนอร์ส่วนหัว * * @param int $sortOrder * @return อาร์เรย์ */ ฟังก์ชันที่ได้รับการป้องกัน getHeaderContainerConfig($sortOrder) { กลับ [ 'ข้อโต้แย้ง' => [ 'ข้อมูล' => [ 'config' => [ 'label' => null, 'formElement' => คอนเทนเนอร์::NAME, 'componentType' => คอนเทนเนอร์::NAME, 'แม่แบบ' => 'ui/แบบฟอร์ม/ส่วนประกอบ/ซับซ้อน', 'sortOrder' => $sortOrder, 'content' => __('คุณสามารถเขียนข้อความได้ที่นี่'), ], ], ], 'เด็ก' => [], ]; } /** * ตัวอย่างฟิลด์ข้อความ config * * @param $sortOrder * @return อาร์เรย์ */ ฟังก์ชันที่ได้รับการป้องกัน getTextFieldConfig($sortOrder) { กลับ [ 'ข้อโต้แย้ง' => [ 'ข้อมูล' => [ 'config' => [ 'label' => __('ตัวอย่างฟิลด์ข้อความ'), 'formElement' => ฟิลด์::NAME, 'componentType' => อินพุต::NAME, 'dataScope' => คงที่::FIELD_NAME_TEXT, 'dataType' => Number::NAME, 'sortOrder' => $sortOrder, ], ], ], ]; } /** * ตัวอย่างเลือกฟิลด์ config * * @param $sortOrder * @return อาร์เรย์ */ ฟังก์ชันที่ได้รับการป้องกัน getSelectFieldConfig($sortOrder) { กลับ [ 'ข้อโต้แย้ง' => [ 'ข้อมูล' => [ 'config' => [ 'label' => __('Options Select'), 'componentType' => ฟิลด์::NAME, 'formElement' => เลือก::NAME, 'dataScope' => คงที่::FIELD_NAME_SELECT, 'dataType' => ข้อความ::NAME, 'sortOrder' => $sortOrder, 'options' => $this->_getOptions(), 'มองเห็นได้' => จริง 'ปิดการใช้งาน' => เท็จ ], ], ], ]; } /** * ตัวอย่างการกำหนดค่าฟิลด์แบบเลือกได้หลายรายการ * * @param $sortOrder * @return อาร์เรย์ */ ฟังก์ชันที่ได้รับการป้องกัน getMultiSelectFieldConfig($sortOrder) { กลับ [ 'ข้อโต้แย้ง' => [ 'ข้อมูล' => [ 'config' => [ 'label' => __('ตัวเลือกหลายตัวเลือก'), 'componentType' => ฟิลด์::NAME, 'formElement' => MultiSelect::NAME, 'dataScope' => คงที่::FIELD_NAME_MULTISELECT, 'dataType' => ข้อความ::NAME, 'sortOrder' => $sortOrder, 'options' => $this->_getOptions(), 'มองเห็นได้' => จริง 'ปิดการใช้งาน' => เท็จ ], ], ], ]; } /** * รับตัวเลือกตัวอย่างเป็นอาร์เรย์ตัวเลือก: * [ * label => สตริง * ค่า => option_id * ] * * @return อาร์เรย์ */ ฟังก์ชันที่ได้รับการป้องกัน _getOptions() { ตัวเลือก $ = [ 1 => [ 'label' => __('ตัวเลือก 1'), 'value' => 1 ], 2 => [ 'label' => __('ตัวเลือก 2'), 'ค่า' => 2 ], 3 => [ 'label' => __('ตัวเลือก 3'), 'value' => 3 ], ]; ส่งคืนตัวเลือก $; } } ?>
ในตัวอย่างนี้ เราจำเป็นต้องใช้ข้อมูลเมตาของฟอร์ม UI ที่มีอยู่แล้วรวมเข้าด้วยกัน (ไม่เขียนซ้ำ!) กับข้อมูลใหม่ของเรา:
<?php /** * รวม meta-data ที่มีอยู่กับ meta-data ของเรา (อย่าเขียนทับ!) * * @return เป็นโมฆะ */ ฟังก์ชันที่ได้รับการป้องกัน addCustomFieldset() { $this->meta = array_merge_recursive( $this->เมตา, [ คงที่::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(), ] ); } ?>
เมื่อเสร็จแล้ว เพิ่ม fieldset ใหม่ให้กับเมธอด getFieldsetConfig:
<?php /** * ประกาศ fieldset config . ของเรา * * @return อาร์เรย์ */ ฟังก์ชันที่ได้รับการป้องกัน getFieldsetConfig() { กลับ [ 'ข้อโต้แย้ง' => [ 'ข้อมูล' => [ 'config' => [ 'label' => __('ชื่อชุดฟิลด์'), 'componentType' => Fieldset::NAME, 'dataScope' => static::DATA_SCOPE_PRODUCT, // บันทึกข้อมูลใน data data 'provider' => static::DATA_SCOPE_PRODUCT . '_แหล่งข้อมูล', 'ns' => คงที่::FORM_NAME, 'พับได้' => จริง 'sortOrder' => 10, 'เปิด' => จริง ], ], ], 'ลูก' => [ คงที่::CONTAINER_HEADER_NAME => $this->getHeaderContainerConfig(10), คงที่::FIELD_NAME_TEXT => $this->getTextFieldConfig(20), คงที่::FIELD_NAME_SELECT => $this->getSelectFieldConfig(30), คงที่::FIELD_NAME_MULTISELECT => $this->getMultiSelectFieldConfig(40), ], ]; } ?>
เราสืบทอดจากตัวแก้ไขฟอร์ม UI ของผลิตภัณฑ์นามธรรม และใช้เนมสเปซและข้อมูลเป็นผู้ให้บริการ: 'provider' => static::DATA_SCOPE_PRODUCT '_data_source' (โดยที่ DATA_SCOPE_PRODUCT คือบรรทัด 'data.product')
ตัวเลือก componentType เป็นหนึ่งในตัวเลือกหลักและรับผิดชอบประเภทส่วนประกอบ ตัวเลือกที่ยุบได้มีหน้าที่ในการยุบและขยายชุดข้อมูลของเรา และตัวเลือกเปิดจะกำหนดว่าชุดฟิลด์จะเปิดขึ้นตามค่าเริ่มต้นในระหว่างการวาดแบบฟอร์มหรือไม่
จากนั้น เราจึงเพิ่มส่วนหัวให้กับชุดฟิลด์ของเราในเมธอด getHeaderContainerConfig และตัวอย่างฟิลด์ 3 ตัวอย่าง ได้แก่ ข้อความ เลือก และการเลือกหลายรายการ อย่างไรก็ตาม ผลิตภัณฑ์และแบบฟอร์มของเราจะไม่ได้รับข้อมูลจนกว่าเราจะเพิ่มลงในวิธี modifiedData แต่เรามีความสามารถในการส่งและสกัดกั้นข้อมูลในระหว่างการบันทึก
มาดูกันว่ารูปร่างหน้าตาเป็นอย่างไร:
การบันทึกข้อมูลเกิดขึ้นภายในไฟล์ควบคุมผลิตภัณฑ์ 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="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" /> </event> </config>
จากนั้น สร้างคลาสของผู้สังเกตการณ์ที่เราชี้ไปที่แอตทริบิวต์อินสแตนซ์ – app/code/Vendor/Product/Observer/ProductSaveAfter.php:
<?php เนมสเปซ Vendor\Product\Observer; ใช้ \Magento\Framework\Event\ObserverInterface; ใช้ \Magento\Framework\Event\Observer เป็น EventObserver; ใช้ Vendor\Product\Ui\DataProvider\Product\Form\Modifier\CustomFieldset; คลาส ProductSaveAfter ใช้ ObserverInterface { /** * @param EventObserver $ ผู้สังเกตการณ์ */ เรียกใช้ฟังก์ชันสาธารณะ (\Magento\Framework\Event\Observer $observer) { /** @var \Magento\Catalog\Model\Product $product */ $product = $observer->getEvent()->getProduct(); ถ้า (!$ ผลิตภัณฑ์) { กลับ; } $exampleTextField = $product->getData(CustomFieldset::FIELD_NAME_TEXT); $exampleTextField = $product->getData(CustomFieldset::FIELD_NAME_TEXT); $exampleSelectField = $product->getData(CustomFieldset::FIELD_NAME_SELECT); $exampleSelectField = $product->getData(CustomFieldset::FIELD_NAME_SELECT); $exampleMultiSelectField = $product->getData(CustomFieldset::FIELD_NAME_MULTISELECT); $exampleMultiSelectField = $product->getData(CustomFieldset::FIELD_NAME_MULTISELECT); // จัดการข้อมูลที่นี่ } } ?>
ข้อมูลในผู้สังเกต:
ตอนนี้คุณสามารถเรียกแบบจำลองของคุณเองจากผู้สังเกตการณ์และบันทึกข้อมูลในนั้นหรือแก้ไขตามที่คุณต้องการ
ระวัง! หากการบันทึกโมเดลของคุณเชื่อมโยงกับการบันทึกผลิตภัณฑ์ อาจนำไปสู่การเรียกซ้ำ