วิธีง่ายๆ ในการเพิ่ม 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);

        // จัดการข้อมูลที่นี่
    }
}
?>

ข้อมูลในผู้สังเกต:

ตอนนี้คุณสามารถเรียกแบบจำลองของคุณเองจากผู้สังเกตการณ์และบันทึกข้อมูลในนั้นหรือแก้ไขตามที่คุณต้องการ

ระวัง! หากการบันทึกโมเดลของคุณเชื่อมโยงกับการบันทึกผลิตภัณฑ์ อาจนำไปสู่การเรียกซ้ำ