As Administrator I want to be able to upload files for each products in order to show link on frontend.
I created upgrade script to create attribute with this properties:
'type' => 'varchar',
'input' => 'file',
'label' => 'Datasheet',
'required' => false,
'visible_on_front' => true,
'backend' => 'My\Module\Model\Product\Attribute\Backend\Datasheet'
Here is my backend model:
namespace My\Module\Model\Product\Attribute\Backend;
use Magento\Framework\App\Filesystem\DirectoryList;
class Datasheet extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
{
const MEDIA_SUBFOLDER = 'datasheet';
protected $_uploaderFactory;
protected $_filesystem;
protected $_fileUploaderFactory;
protected $_logger;
/**
* Construct
*
* @param \Psr\Log\LoggerInterface $logger
* @param \Magento\Framework\Filesystem $filesystem
* @param \Magento\Framework\File\UploaderFactory $uploaderFactory
*/
public function __construct(
\Psr\Log\LoggerInterface $logger,
\Magento\Framework\Filesystem $filesystem,
\Magento\Framework\File\UploaderFactory $uploaderFactory
) {
$this->_filesystem = $filesystem;
$this->_uploaderFactory = $uploaderFactory;
$this->_logger = $logger;
}
public function afterSave($object)
{
$attributeName = $this->getAttribute()->getName();
$fileName = $this->uploadFileAndGetName($attributeName, $this->_filesystem->getDirectoryWrite(DirectoryList::MEDIA)->getAbsolutePath(self::MEDIA_SUBFOLDER));
if ($fileName) {
$object->setData($attributeName, $fileName);
$this->getAttribute()->getEntity()->saveAttribute($object, $attributeName);
}
return $this;
}
public function uploadFileAndGetName($input, $destinationFolder)
{
try {
$uploader = $this->_uploaderFactory->create(array('fileId' => 'product['.$input.']'));
$uploader->setAllowedExtensions(['pdf']);
$uploader->setAllowRenameFiles(true);
$uploader->setFilesDispersion(true);
$uploader->setAllowCreateFolders(true);
$uploader->save($destinationFolder);
return $uploader->getUploadedFileName();
} catch (\Exception $e) {
if ($e->getCode() != \Magento\Framework\File\Uploader::TMP_NAME_EMPTY) {
throw new \FrameworkException($e->getMessage());
}
}
return '';
}
}
Attribute is shown in backend and saves value in database.
PROBLEM
Attribute value is not shown in backend.
References:
Best Answer
Investigation
file
input is not implemented in Magento 2.1 yet.in
vendor/magento/module-ui/view/base/web/templates/form/element/media.html
there is only uploader and no view and delete button:It will be implemented in next Magento2 release hopefully.
So I thought to implement a custom renderer, but
there is a bug probably
better use PHP modifier in UI components instead of input renderer, if you need to customise your custom attribute in product edit form Magento 2
Solution
Magento2 way is to use UI components and PHP Modifiers
Create 3 files:
etc/adminhtml/di.xml
- dependency injection configuration for adminhtmlyour_module_datasheet
can be any name.With
sortOrder
from 10 to 50 it didn't work for me.$meta
variable in Modifier was empty.Ui/DataProvider/Product/Form/Modifier/Datasheet.php
- php modifierview/adminhtml/web/template/grid/filters/elements/datasheet.html
- knockout js templateIt is still looks dirty to me and a lot of things to improve.
Alternatives
I found some interesting files, which can bring you other ideas how to solve it:
vendor/magento/module-catalog/view/adminhtml/ui_component/design_config_form.xml
vendor/magento/module-ui/view/base/ui_component/etc/definition.xml