將帶有字段的字段集添加到 UI 表單的簡單方法

已發表: 2016-08-23

在本文中,我們將創建一個簡單的模塊,該模塊將在產品編輯 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 :

 {
        “名稱”:“供應商/模塊產品”,
        “描述”:“不適用”,
        “類型”:“magento2-模塊”,
        “版本”:“1.0.0”,
        “執照”: [
            "OSL-3.0",
            “AFL-3.0”
        ],
        “自動加載”:{
            “文件”:[
                “註冊.php”
            ],
            “psr-4”:{
                “供應商\\產品\\”:“”
            }
        }
    }

現在,使用 Magento_Catalog 模塊的依賴項創建模塊的主 XML 文件 app/code/Vendor/Product/etc/module.xml,因為我們的模態窗口將添加到它的表單中:

 <?xml 版本="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"/>
            </序列>
        </模塊>
    </配置>

通過輸入以下內容啟用模塊:bin/magento module:enable Vendor_Product 和 bin/magento setup:upgrade 在根 Magento 目錄中。

然後,添加模塊的內容:UI 表單元數據和添加的虛擬類型。

創建文件 app/code/Vendor/Product/etc/adminhtml/di.xml。 我們將在裡面放置一個修飾符:

 <?xml 版本="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="修飾符" 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>
                </項目>
            </參數>
        </參數>
    </virtualType>
</配置>

修飾符負責添加數據以及對元素和 UI 表單組件進行一些操作。 修改器的接口有 2 個主要方法(它們應該始終存在):

 <?php
    /**
     * 版權所有 2016 Magento。 版權所有。
     * 有關許可證的詳細信息,請參閱 COPYING.txt。
     */
    命名空間 Magento\Ui\DataProvider\Modifier;
    
    /**
     * 類修飾符接口
     */
    接口修飾符接口
    {
        /**
         * @param 數組 $data
         * @return 數組
         */
        公共函數 modifyData(數組 $data);
    
        /**
         * @param 數組 $meta
         * @return 數組
         */
        公共函數 modifyMeta(array $meta);
    }
    ?>

我們將在本例中使用 modifyMeta 方法。 modifyData 方法將在下一篇文章中解釋。

現在,使用產品編輯頁面的自定義字段集創建修改器文件 (app/code/Vendor/Product/Ui/DataProvider/Product/Form/Modifier/CustomFieldset.php),並用以下字段填充:

 <?php
命名空間供應商\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
{

    // 組件索引
    常量 CUSTOM_FIELDSET_INDEX = 'custom_fieldset';
    常量 CUSTOM_FIELDSET_CONTENT = 'custom_fieldset_content';
    常量 CONTAINER_HEADER_NAME = 'custom_fieldset_content_header';

    // 字段名稱
    常量 FIELD_NAME_TEXT = 'example_text_field';
    常量 FIELD_NAME_SELECT = 'example_select_field';
    常量 FIELD_NAME_MULTISELECT = 'example_multiselect_field';

    /**
     * @var \Magento\Catalog\Model\Locator\LocatorInterface
     */
    受保護的$定位器;

    /**
     * @var 數組管理器
     */
    受保護的 $arrayManager;

    /**
     * @var 網址接口
     */
    受保護的 $urlBuilder;

    /**
     * @var 數組
     */
    受保護的 $meta = [];

    /**
     * @param 定位器接口 $locator
     * @param ArrayManager $arrayManager
     * @param UrlInterface $urlBuilder
     */
    公共函數 __construct(
        定位器接口 $locator,
        陣列管理器 $陣列管理器,
        網址接口 $urlBuilder
    ) {
        $this->定位器 = $定位器;
        $this->arrayManager = $arrayManager;
        $this->urlBuilder = $urlBuilder;
    }

    /**
     * 數據修飾符,在我們的示例中什麼都不做。
     *
     * @param 數組 $data
     * @return 數組
     */
    公共函數 modifyData(數組 $data)
    {
        返回$數據;
    }

    /**
     * 元數據修飾符:添加我們的字段集
     *
     * @param 數組 $meta
     * @return 數組
     */
    公共函數 modifyMeta(數組 $meta)
    {
        $this->meta = $meta;
        $this->addCustomFieldset();

        返回 $this->meta;
    }

    /**
     * 將現有元數據與我們的元數據合併(不要覆蓋它!)
     *
     * @return 無效
     */
    受保護的函數 addCustomFieldset()
    {
        $this->meta = array_merge_recursive(
            $this->元,
            [
                靜態::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(),
            ]
        );
    }

    /**
     * 聲明我們的字段集配置
     *
     * @return 數組
     */
    受保護的函數 getFieldsetConfig()
    {
        返回 [
            '論據' => [
                '數據' => [
                    '配置' => [
                        '標籤' => __('字段集標題'),
                        'componentType' => 字段集::NAME,
                        'dataScope' => static::DATA_SCOPE_PRODUCT, // 保存產品數據中的數據
                        '提供者' => 靜態::DATA_SCOPE_PRODUCT 。 '_數據源',
                        'ns' => 靜態::FORM_NAME,
                        '可折疊' => 真的,
                        '排序順序' => 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)
    {
        返回 [
            '論據' => [
                '數據' => [
                    '配置' => [
                        '標籤' => 空,
                        'formElement' => 容器::NAME,
                        'componentType' => 容器::NAME,
                        '模板' => 'ui/form/components/complex',
                        'sortOrder' => $sortOrder,
                        'content' => __('你可以在這裡寫任何文字'),
                    ],
                ],
            ],
            '孩子' => [],
        ];
    }

    /**
     * 示例文本字段配置
     *
     * @param $sortOrder
     * @return 數組
     */
    受保護的函數 getTextFieldConfig($sortOrder)
    {
        返回 [
            '論據' => [
                '數據' => [
                    '配置' => [
                        'label' => __('示例文本字段'),
                        'formElement' => 字段::NAME,
                        'componentType' => 輸入::NAME,
                        'dataScope' => 靜態::FIELD_NAME_TEXT,
                        'dataType' => 編號::NAME,
                        'sortOrder' => $sortOrder,
                    ],
                ],
            ],
        ];
    }

    /**
     * 示例選擇字段配置
     *
     * @param $sortOrder
     * @return 數組
     */
    受保護的函數 getSelectFieldConfig($sortOrder)
    {
        返回 [
            '論據' => [
                '數據' => [
                    '配置' => [
                        '標籤' => __('選項選擇'),
                        'componentType' => 字段::NAME,
                        'formElement' => 選擇::名稱,
                        'dataScope' => 靜態::FIELD_NAME_SELECT,
                        'dataType' => 文本::NAME,
                        'sortOrder' => $sortOrder,
                        '選項' => $this->_getOptions(),
                        '可見' => 真,
                        '禁用' => 假,
                    ],
                ],
            ],
        ];
    }

    /**
     * 示例多選字段配置
     *
     * @param $sortOrder
     * @return 數組
     */
    受保護的函數 getMultiSelectFieldConfig($sortOrder)
    {
        返回 [
            '論據' => [
                '數據' => [
                    '配置' => [
                        '標籤' => __('選項多選'),
                        'componentType' => 字段::NAME,
                        'formElement' => MultiSelect::NAME,
                        'dataScope' => 靜態::FIELD_NAME_MULTISELECT,
                        'dataType' => 文本::NAME,
                        'sortOrder' => $sortOrder,
                        '選項' => $this->_getOptions(),
                        '可見' => 真,
                        '禁用' => 假,
                    ],
                ],
            ],
        ];
    }

    /**
     * 獲取示例選項作為選項數組:
     * [
     * 標籤 => 字符串,
     * 值 => option_id
     * ]
     *
     * @return 數組
     */
    受保護的函數 _getOptions()
    {
        $選項= [
            1 => [
                '標籤' => __('選項 1'),
                '價值' => 1
            ],
            2 => [
                '標籤' => __('選項 2'),
                '價值' => 2
            ],
            3 => [
                '標籤' => __('選項 3'),
                '價值' => 3
            ],
        ];

        返回$選項;
    }
}
?>

在此示例中,我們需要獲取現有的 UI 表單元數據並將其與我們的新數據合併(而不是重寫!):

 <?php
/**
 * 將現有元數據與我們的元數據合併(不要覆蓋它!)
 *
 * @return 無效
 */
受保護的函數 addCustomFieldset()
{
    $this->meta = array_merge_recursive(
        $this->元,
        [
            靜態::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(),
        ]
    );
}
?>

完成後,將新字段集添加到 getFieldsetConfig 方法:

 <?php
/**
 * 聲明我們的字段集配置
 *
 * @return 數組
 */
受保護的函數 getFieldsetConfig()
{
    返回 [
        '論據' => [
            '數據' => [
                '配置' => [
                    '標籤' => __('字段集標題'),
                    'componentType' => 字段集::NAME,
                    'dataScope' => static::DATA_SCOPE_PRODUCT, // 保存產品數據中的數據
                    '提供者' => 靜態::DATA_SCOPE_PRODUCT 。 '_數據源',
                    'ns' => 靜態::FORM_NAME,
                    '可折疊' => 真的,
                    '排序順序' => 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-form 修飾符繼承,並將其命名空間和數據用作提供者:'provider' => static::DATA_SCOPE_PRODUCT。 '_data_source'(其中 DATA_SCOPE_PRODUCT 是 'data.product' 行)。

componentType 選項是主要選項之一,負責組件類型。 collapsible 選項負責折疊和擴展我們的字段集。 並且 open 選項定義了在表單繪製過程中字段集是否默認打開。

然後,我們因此在 getHeaderContainerConfig 方法中向我們的字段集添加一個標題和 3 個字段示例:文本、選擇和多選。 但是,在我們將數據添加到 modifyData 方法之前,我們的產品和表單不會接收數據。 但是我們有能力在保存過程中傳輸和攔截數據。

讓我們看看表單的外觀:

數據保存發生在主執行方法中的產品控制器文件 vendor/magento/module-catalog/Controller/Adminhtml/Product/Save.php 中。 如果一切都以正確的方式完成,那麼我們的數據將正確顯示在此方法的輸入數據中:

請注意,如果您的產品從一開始就沒有這些屬性,您應該手動保存它們。 您可以在觀察者中執行此操作。

首先,在 app/code/Vendor/Product/etc/adminhtml/events.xml 文件中聲明它(我們使用 adminhtml 範圍,因為前端不存在表單):

 <?xml 版本="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" />
    </事件>
</配置>

然後,創建我們在實例屬性中指向的觀察者類——app/code/Vendor/Product/Observer/ProductSaveAfter.php:

 <?php
命名空間供應商\產品\觀察者;

使用 \Magento\Framework\Event\ObserverInterface;
使用 \Magento\Framework\Event\Observer 作為 EventObserver;
使用 Vendor\Product\Ui\DataProvider\Product\Form\Modifier\CustomFieldset;

類 ProductSaveAfter 實現 ObserverInterface
{

    /**
     * @param EventObserver $observer
     */
    公共函數執行(\Magento\Framework\Event\Observer $observer)
    {
        /** @var \Magento\Catalog\Model\Product $product */
        $product = $observer->getEvent()->getProduct();
        如果(!$產品){
            返回;
        }

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

        // 在這裡操作數據
    }
}
?>

觀察者中的數據:

現在,您可以從觀察者調用自己的模型並將數據保存在其中或根據需要進行修改。

當心! 如果你的模型的保存與產品的保存有關,那麼它可能會導致遞歸。