Cara Mudah untuk Menambahkan Fieldset dengan Fields ke UI-Form

Diterbitkan: 2016-08-23

Pada artikel ini, kita akan membuat modul sederhana yang akan menambahkan fieldset dengan field di formulir UI pengeditan produk. Selain itu, kami akan membuat pengamat untuk mencegat data ini selama penyimpanan produk.

Pertama, kita perlu membuat modul Vendor_Product:

1. Buat aplikasi direktori/kode/Vendor/Produk
2. Buat file registrasi app/code/Vendor/Product/registration.php dengan isi sebagai berikut:

 <?php
    \Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE,
        'Produk_Penjual',
        __DIR__
    );
    ?>

Buat file komposer (jika Anda berencana untuk mentransfer modul) app/code/Vendor/Module/composer.json :

 {
        "name": "vendor/modul-produk",
        "deskripsi": "T/A",
        "type": "magento2-modul",
        "versi": "1.0.0",
        "lisensi": [
            "OSL-3.0",
            "AFL-3.0"
        ],
        "muat otomatis": {
            "berkas": [
                "registrasi.php"
            ],
            "psr-4": {
                "Vendor\\Produk\\": ""
            }
        }
    }

Sekarang, buat file XML utama app/code/Vendor/Product/etc/module.xml dengan ketergantungan dari modul Magento_Catalog karena jendela modal kita akan ditambahkan ke bentuknya:

 <?xml versi="1.0"?>
    <config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
        <nama modul="Vendor_Product" setup_version="1.0.0">
            <urutan>
                <nama modul="Magento_Catalog"/>
            </urutan>
        </modul>
    </config>

Aktifkan modul dengan memasukkan yang berikut ini: bin/magento module:enable Vendor_Product dan bin/magento setup:upgrade di direktori root Magento.

Kemudian, tambahkan konten modul: meta-data bentuk UI dan tipe virtual untuk penambahannya.

Buat file app/code/Vendor/Product/etc/adminhtml/di.xml. Kami akan menempatkan pengubah di dalam:

 <?xml versi="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">
        <argumen>
            <nama argumen="pengubah" xsi:type="array">
                <nama item="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>
            </argumen>
        </argumen>
    </virtualType>
</config>

Pengubah bertanggung jawab untuk penambahan data dan beberapa manipulasi dengan elemen dan komponen bentuk UI. Ada 2 metode utama yang berasal dari antarmuka pengubah (mereka harus selalu ada):

 <?php
    /**
     * Hak Cipta 2016 Magento. Seluruh hak cipta.
     * Lihat COPYING.txt untuk detail lisensi.
     */
    namespace Magento\Ui\DataProvider\Modifier;
    
    /**
     * Antarmuka Pengubah Kelas
     */
    Antarmuka Pengubah Antarmuka
    {
        /**
         * @param array $data
         * @return array
         */
        fungsi publik memodifikasiData(array $data);
    
        /**
         * @param array $meta
         * @return array
         */
        fungsi publik memodifikasiMeta(array $meta);
    }
    ?>

Kita akan menggunakan metode modifikasiMeta dalam contoh ini. Metode modifikasiData akan dijelaskan pada artikel selanjutnya.

Sekarang, buat file pengubah (app/code/Vendor/Product/Ui/DataProvider/Product/Form/Modifier/CustomFieldset.php) dengan fieldset khusus untuk halaman pengeditan produk dan isi dengan kolom:

 <?php
namespace Vendor\Product\Ui\DataProvider\Product\Form\Modifier;

gunakan Magento\Catalog\Model\Locator\LocatorInterface;
gunakan Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier;
gunakan Magento\Framework\Stdlib\ArrayManager;
gunakan Magento\Framework\UrlInterface;
gunakan Magento\Ui\Component\Container;
gunakan Magento\Ui\Component\Form\Fieldset;
gunakan Magento\Ui\Component\Form\Element\DataType\Number;
gunakan Magento\Ui\Component\Form\Element\DataType\Text;
gunakan Magento\Ui\Component\Form\Element\Input;
gunakan Magento\Ui\Component\Form\Element\Select;
gunakan Magento\Ui\Component\Form\Element\MultiSelect;
gunakan Magento\Ui\Component\Form\Field;

kelas CustomFieldset memperluas AbstractModifier
{

    // Indeks komponen
    const CUSTOM_FIELDSET_INDEX = 'custom_fieldset';
    const CUSTOM_FIELDSET_CONTENT = 'custom_fieldset_content';
    const CONTAINER_HEADER_NAME = 'custom_fieldset_content_header';

    // Nama bidang
    const FIELD_NAME_TEXT = 'example_text_field';
    const FIELD_NAME_SELECT = 'example_select_field';
    const FIELD_NAME_MULTISELECT = 'contoh_multiselect_field';

    /**
     * @var \Magento\Catalog\Model\Locator\LocatorInterface
     */
    dilindungi $locator;

    /**
     * @var ArrayManager
     */
    dilindungi $arrayManager;

    /**
     * @var UrlInterface
     */
    dilindungi $urlBuilder;

    /**
     * @var array
     */
    dilindungi $meta = [];

    /**
     * @param LocatorInterface $locator
     * @param ArrayManager $arrayManager
     * @param UrlInterface $urlBuilder
     */
    fungsi publik __konstruksi(
        LocatorInterface $pencari,
        ArrayManager $arrayManager,
        UrlInterface $urlBuilder
    ) {
        $this->locator = $locator;
        $this->arrayManager = $arrayManager;
        $this->urlBuilder = $urlBuilder;
    }

    /**
     * Pengubah data, tidak melakukan apa pun dalam contoh kita.
     *
     * @param array $data
     * @return array
     */
    fungsi publik memodifikasiData(array $data)
    {
        kembalikan $data;
    }

    /**
     * Pengubah meta-data: menambahkan fieldset kita
     *
     * @param array $meta
     * @return array
     */
    fungsi publik memodifikasiMeta(array $meta)
    {
        $ini->meta = $meta;
        $this->addCustomFieldset();

        kembalikan $this->meta;
    }

    /**
     * Gabungkan meta-data yang ada dengan meta-data kami (jangan ditimpa!)
     *
     * @kembali batal
     */
    fungsi yang dilindungi addCustomFieldset()
    {
        $this->meta = array_merge_recursive(
            $ini->meta,
            [
                static::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(),
            ]
        );
    }

    /**
     * Deklarasikan konfigurasi fieldset kami
     *
     * @return array
     */
    fungsi yang dilindungi getFieldsetConfig()
    {
        kembali [
            'argumen' => [
                'data' => [
                    'konfigurasi' => [
                        'label' => __('Judul Fieldset'),
                        'componentType' => Fieldset::NAME,
                        'dataScope' => static::DATA_SCOPE_PRODUCT, // simpan data di data produk
                        'penyedia' => static::DATA_SCOPE_PRODUCT . '_sumber data',
                        'ns' => statis::FORM_NAME,
                        'dapat dilipat' => benar,
                        'sortOrder' => 10,
                        'dibuka' => benar,
                    ],
                ],
            ],
            'anak-anak' => [
                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),
            ],
        ];
    }

    /**
     * Dapatkan konfigurasi untuk wadah header
     *
     * @param int $sortOrder
     * @return array
     */
    fungsi yang dilindungi getHeaderContainerConfig($sortOrder)
    {
        kembali [
            'argumen' => [
                'data' => [
                    'konfigurasi' => [
                        'label' => nol,
                        'formElement' => Wadah::NAME,
                        'componentType' => Wadah::NAME,
                        'templat' => 'ui/form/komponen/kompleks',
                        'sortOrder' => $sortOrder,
                        'content' => __('Anda dapat menulis teks apa saja di sini'),
                    ],
                ],
            ],
            'anak-anak' => [],
        ];
    }

    /**
     * Contoh konfigurasi bidang teks
     *
     * @param $sortOrder
     * @return array
     */
    fungsi yang dilindungi getTextFieldConfig($sortOrder)
    {
        kembali [
            'argumen' => [
                'data' => [
                    'konfigurasi' => [
                        'label' => __('Contoh Bidang Teks'),
                        'formElement' => Bidang::NAME,
                        'componentType' => Masukan::NAME,
                        'dataScope' => statis::FIELD_NAME_TEXT,
                        'dataType' => Nomor::NAME,
                        'sortOrder' => $sortOrder,
                    ],
                ],
            ],
        ];
    }

    /**
     * Contoh konfigurasi bidang pilih
     *
     * @param $sortOrder
     * @return array
     */
    fungsi yang dilindungi getSelectFieldConfig($sortOrder)
    {
        kembali [
            'argumen' => [
                'data' => [
                    'konfigurasi' => [
                        'label' => __('Pilihan Opsi'),
                        'componentType' => Bidang::NAME,
                        'formElement' => Pilih::NAME,
                        'dataScope' => statis::FIELD_NAME_SELECT,
                        'dataType' => Teks::NAME,
                        'sortOrder' => $sortOrder,
                        'pilihan' => $this->_getOptions(),
                        'terlihat' => benar,
                        'dinonaktifkan' => salah,
                    ],
                ],
            ],
        ];
    }

    /**
     * Contoh konfigurasi bidang multi-pilih
     *
     * @param $sortOrder
     * @return array
     */
    fungsi yang dilindungi getMultiSelectFieldConfig($sortOrder)
    {
        kembali [
            'argumen' => [
                'data' => [
                    'konfigurasi' => [
                        'label' => __('Pilihan Banyak Pilihan'),
                        'componentType' => Bidang::NAME,
                        'formElement' => MultiPilih::NAME,
                        'dataScope' => static::FIELD_NAME_MULTISELECT,
                        'dataType' => Teks::NAME,
                        'sortOrder' => $sortOrder,
                        'pilihan' => $this->_getOptions(),
                        'terlihat' => benar,
                        'dinonaktifkan' => salah,
                    ],
                ],
            ],
        ];
    }

    /**
     * Dapatkan opsi contoh sebagai larik opsi:
     * [
     * label => string,
     * nilai => option_id
     * ]
     *
     * @return array
     */
    fungsi yang dilindungi _getOptions()
    {
        $pilihan = [
            1 => [
                'label' => __('Opsi 1'),
                'nilai' => 1
            ],
            2 => [
                'label' => __('Opsi 2'),
                'nilai' => 2
            ],
            3 => [
                'label' => __('Opsi 3'),
                'nilai' => 3
            ],
        ];

        kembali $options;
    }
}
?>

Dalam contoh ini kita perlu mengambil meta-data bentuk UI yang ada dan menggabungkannya (bukan menulis ulang!) dengan data baru kita:

 <?php
/**
 * Gabungkan meta-data yang ada dengan meta-data kami (jangan ditimpa!)
 *
 * @kembali batal
 */
fungsi yang dilindungi addCustomFieldset()
{
    $this->meta = array_merge_recursive(
        $ini->meta,
        [
            static::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(),
        ]
    );
}
?>

Setelah selesai, tambahkan fieldset baru ke metode getFieldsetConfig:

 <?php
/**
 * Deklarasikan konfigurasi fieldset kami
 *
 * @return array
 */
fungsi yang dilindungi getFieldsetConfig()
{
    kembali [
        'argumen' => [
            'data' => [
                'konfigurasi' => [
                    'label' => __('Judul Fieldset'),
                    'componentType' => Fieldset::NAME,
                    'dataScope' => static::DATA_SCOPE_PRODUCT, // simpan data di data produk
                    'penyedia' => static::DATA_SCOPE_PRODUCT . '_sumber data',
                    'ns' => statis::FORM_NAME,
                    'dapat dilipat' => benar,
                    'sortOrder' => 10,
                    'dibuka' => benar,
                ],
            ],
        ],
        'anak-anak' => [
            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),
        ],
    ];
}
?>

Kami mewarisi dari pengubah bentuk UI produk abstrak dan menggunakan namespace dan datanya sebagai penyedia: 'provider' => static::DATA_SCOPE_PRODUCT . '_data_source' (dengan DATA_SCOPE_PRODUCT adalah baris 'data.product').

Opsi componentType adalah salah satu opsi utama dan bertanggung jawab untuk tipe komponen. Opsi yang dapat diciutkan bertanggung jawab untuk menciutkan dan memperluas kumpulan bidang kami. Dan opsi buka menentukan apakah fieldset akan terbuka secara default selama menggambar formulir.

Kemudian, kami menambahkan header ke fieldset kami di metode getHeaderContainerConfig dan 3 contoh bidang: teks, pilih, dan pilih banyak. Namun, produk dan formulir kami tidak akan menerima data sampai kami menambahkannya ke metode modifikasiData. Tetapi kami memiliki kemampuan untuk mengirim dan mencegat data selama penyimpanan.

Mari kita lihat bagaimana bentuknya:

Penyimpanan data terjadi di dalam file pengontrol produk vendor/magento/module-catalog/Controller/Adminhtml/Product/Save.php dalam metode eksekusi utama. Jika semuanya telah dilakukan dengan cara yang benar, maka data kita akan ditampilkan dengan benar dalam data input metode ini:

Catatan, jika produk Anda tidak memiliki atribut tersebut dari awal, Anda harus menyimpannya secara manual. Anda dapat melakukan ini di pengamat.

Pertama, deklarasikan dalam file app/code/Vendor/Product/etc/adminhtml/events.xml (kami menggunakan lingkup adminhtml karena formulir tidak ada di front-end):

 <?xml versi="1.0"?>
<config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <nama acara="catalog_product_save_after">
        <nama pengamat="save_example_data" instance="Vendor\Product\Observer\ProductSaveAfter" />
    </acara>
</config>

Kemudian, buat kelas pengamat yang kita tunjuk di atribut instance – app/code/Vendor/Product/Observer/ProductSaveAfter.php:

 <?php
namespace Vendor\Product\Observer;

gunakan \Magento\Framework\Event\ObserverInterface;
gunakan \Magento\Framework\Event\Observer sebagai EventObserver;
gunakan Vendor\Product\Ui\DataProvider\Product\Form\Modifier\CustomFieldset;

kelas ProductSaveAfter mengimplementasikan ObserverInterface
{

    /**
     * @param EventObserver $pengamat
     */
    eksekusi fungsi publik(\Magento\Framework\Event\Observer $observer)
    {
        /** @var \Magento\Catalog\Model\Product $product */
        $produk = $pengamat->getEvent()->getProduct();
        jika (!$produk) {
            kembali;
        }

        $exampleTextField = $product->getData(CustomFieldset::FIELD_NAME_TEXT);
        $exampleSelectField = $product->getData(CustomFieldset::FIELD_NAME_SELECT);
        $exampleMultiSelectField = $product->getData(CustomFieldset::FIELD_NAME_MULTISELECT);

        // Manipulasi data di sini
    }
}
?>

Data di pengamat:

Sekarang, Anda dapat memanggil model Anda sendiri dari pengamat dan menyimpan data di dalamnya atau memodifikasinya sesuai keinginan.

Hati-hati! Jika penyimpanan model Anda terhubung dengan penyimpanan produk, maka itu dapat menyebabkan rekursi.