Magento 2: UI File Uploader Not Passing Data in Product Edit Form

magento2uicomponent

I am working on a module to allow a price matrix to be assigned to a product.

This required a fileuploader field to be added to the product edit form.

I have managed to add the field to the product edit form, created a controller which handles the upload and returns some json to the product edit form, I can see the preview template appear with the correct data in, but when I then try and save the form, this data is not passed within the save request.

UI Component

<?xml version="1.0" encoding="UTF-8"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="pricematrix">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="label" xsi:type="string" translate="true">Price Matrix</item>
                <item name="collapsible" xsi:type="boolean">true</item>
                <item name="sortOrder" xsi:type="number">100</item>
                <item name="dataScope" xsi:type="string">data.product</item>
                <item name="provider" xsi:type="string">product</item>
                <item name="ns" xsi:type="string">product_form</item>
            </item>
        </argument>
        <field name="price_matrix">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">string</item>
                    <item name="label" xsi:type="string" translate="true">Upload Price Matrix</item>
                    <item name="formElement" xsi:type="string">fileUploader</item>
                    <item name="elementTmpl" xsi:type="string">ui/form/element/uploader/uploader</item>
                    <item name="sortOrder" xsi:type="number">1</item>
                    <item name="scopeLabel" xsi:type="string">[STORE]</item>
                    <item name="source" xsi:type="string">product</item>
                    <item name="required" xsi:type="boolean">false</item>
                    <item name="placeholderType" xsi:type="string">document</item>
                    <item name="uploaderConfig" xsi:type="array">
                        <item name="url" xsi:type="url" path="hub_pricematrix/upload/pricematrix"/>
                    </item>
                </item>
            </argument>
        </field>
    </fieldset>
</form>

AJAX Handler

<?php

namespace Hub\Pricematrix\Controller\Adminhtml\Upload;

use Magento\Backend\App\Action;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Filesystem;
use Magento\MediaStorage\Model\File\UploaderFactory;

class Pricematrix extends Action
{
    protected $fileSystem;

    protected $uploaderFactory;

    protected $resultRawFactory;

    protected $allowedExtensions = ['csv'];

    protected $fileId = 'price_matrix';

    public function __construct(
        Action\Context $context,
        Filesystem $fileSystem,
        UploaderFactory $uploaderFactory,
        \Magento\Framework\Controller\Result\RawFactory $resultRawFactory
    ) {
        $this->fileSystem = $fileSystem;
        $this->uploaderFactory = $uploaderFactory;
        $this->resultRawFactory = $resultRawFactory;
        parent::__construct($context);
    }

    public function execute()
    {


        $destinationPath = $this->getDestinationPath();
        try {
            $uploader = $this->uploaderFactory->create(['fileId' => $this->fileId])
                ->setAllowCreateFolders(true)
                ->setAllowedExtensions($this->allowedExtensions)
                ->addValidateCallback('validate', $this, 'validateFile');

            $result = $uploader->save($destinationPath);
            if (!$result) {
                throw new LocalizedException(
                    __('File cannot be saved to path: $1', $destinationPath)
                );
            }

            unset($result['tmp_name']);
            unset($result['path']);
            $result['url'] = "";

            $response = $this->resultRawFactory->create();
            $response->setHeader('Content-type', 'text/plain');
            $response->setContents(json_encode($result));
            return $response;
        } catch (\Exception $e) {
            $result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
        }
    }

    public function validateFile($filePath)
    {
        // todo
    }

    public function getDestinationPath()
    {
        return $this->fileSystem
            ->getDirectoryWrite(DirectoryList::TMP)
            ->getAbsolutePath('/');
    }
}

Backend showing an uploaded CSV

enter image description here

Best Answer

Base on what the core doing

vendor/magento/module-catalog/Controller/Adminhtml/Category/Image/Upload.php

you should change your Ajax Handle to:

    <?php

namespace Hub\Pricematrix\Controller\Adminhtml\Upload;

use Magento\Backend\App\Action;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Filesystem;
use Magento\MediaStorage\Model\File\UploaderFactory;

class Pricematrix extends Action
{
/**
 * Image uploader
 *
 * @var \Magento\Catalog\Model\ImageUploader
 */
protected $imageUploader;

/**
 * Upload constructor.
 *
 * @param \Magento\Backend\App\Action\Context $context
 * @param \Magento\Catalog\Model\ImageUploader $imageUploader
 */
public function __construct(
    \Magento\Backend\App\Action\Context $context,
    \Magento\Catalog\Model\ImageUploader $imageUploader
) {
    parent::__construct($context);
    $this->imageUploader = $imageUploader;
}



/**
 * Upload file controller action
 *
 * @return \Magento\Framework\Controller\ResultInterface
 */
public function execute()
{
    try {
        $result = $this->imageUploader->saveFileToTmpDir('price_matrix');

        $result['cookie'] = [
            'name' => $this->_getSession()->getName(),
            'value' => $this->_getSession()->getSessionId(),
            'lifetime' => $this->_getSession()->getCookieLifetime(),
            'path' => $this->_getSession()->getCookiePath(),
            'domain' => $this->_getSession()->getCookieDomain(),
        ];
    } catch (\Exception $e) {
        $result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
    }
    return $this->resultFactory->create(ResultFactory::TYPE_JSON)->setData($result);
}
}

di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

<virtualType name="Hub\Pricematrix\Upload\ImageUpload" type="Magento\Catalog\Model\ImageUploader">
    <arguments>
        <argument name="baseTmpPath" xsi:type="string">price_matrix/tmp</argument>
        <argument name="basePath" xsi:type="string">price_matrix</argument>
        <argument name="allowedExtensions" xsi:type="array">
            <item name="csv" xsi:type="string">csv</item>
            <item name="jpg" xsi:type="string">jpg</item>
            <item name="gif" xsi:type="string">gif</item>
            <item name="png" xsi:type="string">png</item>
        </argument>
    </arguments>
</virtualType>

<type name="Hub\Pricematrix\Controller\Adminhtml\Upload\Pricematrix">
    <arguments>
        <argument name="imageUploader" xsi:type="object">Hub\Pricematrix\Upload\ImageUpload</argument>
    </arguments>
</type>

Related Topic