i wanna know how can i create a form like this below. Can anybody show me where should i start and what i need to do, to buidl a form like this:
Hello @annq3sivn4281,
Greetings!
To create this type of form you need to follow the below steps:
1. create a registration.php file in the app/code/Milople/ProductAttachment directory.
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Milople_ProductAttachment', __DIR__ );
2. Create a module.xml file in app/code/Milople/ProductAttachment/etc
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Milople_ProductAttachment" setup_version="1.0.0" />
</config>3. Now, create a script to add a product attribute. create a InstallData.php in app/code/Milople/ProductAttachment/Setup
<?php
namespace Milople\ProductAttachment\Setup;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Eav\Setup\EavSetupFactory;
/**
* Class InstallData
* @package Milople\ProductAttachment\Setup
*
* @codeCoverageIgnore
*/
class InstallData implements InstallDataInterface
{
/**
* @var EavSetupFactory
*/
protected $_eavSetupFactory;
public function __construct(
EavSetupFactory $eavSetupFactory
) {
$this->_eavSetupFactory = $eavSetupFactory;
}
/**
* {@inheritdoc}
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$eavSetup = $this->_eavSetupFactory->create(["setup"=>$setup]);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'attachment',
[
'group' => 'Product Attachment',
'type' => 'varchar',
'label' => 'Attachment',
'input' => 'file',
'backend' => 'Milople\ProductAttachment\Model\Product\Attribute\Backend\File',
'frontend' => '',
'class' => '',
'source' => '',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => false,
'user_defined' => true,
'default' => '',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'unique' => false,
'apply_to' => 'simple,configurable', // applicable for simple and configurable product
'used_in_product_listing' => true
]
);
}
}4. Now you have to create a backend model file to upload the product attachment file and save the value in the attachment attribute. So create File.php in app/code/Milople/ProductAttachment/Model/Product/Attribute/Backend
<?php
namespace Milople\ProductAttachment\Model\Product\Attribute\Backend;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend;
class File extends AbstractBackend
{
/**
* @var \Magento\Framework\Filesystem\Driver\File
*/
protected $_file;
/**
* @var \Psr\Log\LoggerInterface
*/
protected $_logger;
/**
* @var \Magento\Framework\Filesystem
*/
protected $_filesystem;
/**
* @var \Magento\MediaStorage\Model\File\UploaderFactory
*/
protected $_fileUploaderFactory;
/**
* Construct
*
* @param \Psr\Log\LoggerInterface $logger
* @param \Magento\Framework\Filesystem $filesystem
* @param \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory
*/
public function __construct(
\Psr\Log\LoggerInterface $logger,
\Magento\Framework\Filesystem $filesystem,
\Magento\Framework\Filesystem\Driver\File $file,
\Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory
) {
$this->_file = $file;
$this->_filesystem = $filesystem;
$this->_fileUploaderFactory = $fileUploaderFactory;
$this->_logger = $logger;
}
public function afterSave($object)
{
$path = $this->_filesystem->getDirectoryRead(
DirectoryList::MEDIA
)->getAbsolutePath(
'catalog/product/attachment/'
);
$delete = $object->getData($this->getAttribute()->getName() . '_delete');
if ($delete) {
$fileName = $object->getData($this->getAttribute()->getName());
$object->setData($this->getAttribute()->getName(), '');
$this->getAttribute()->getEntity()->saveAttribute($object, $this->getAttribute()->getName());
if ($this->_file->is Exists($path.$fileName)) {
$this->_file->deleteFile($path.$fileName);
}
}
if (empty($_FILES['product']['tmp_name'][$this->getAttribute()->getName()])) {
return $this;
}
try {
/** @var $uploader \Magento\MediaStorage\Model\File\Uploader */
$uploader = $this->_fileUpzloaderFactory->create(['fileId' => 'product['.$this->getAttribute()->getName().']']);
$uploader->setAllowRenameFiles(true);
$result = $uploader->save($path);
$object->setData($this->getAttribute()->getName(), $result['file']);
$this->getAttribute()->getEntity()->saveAttribute($object, $this->getAttribute()->getName());
} catch (\Exception $e) {
if ($e->getCode() != \Magento\MediaStorage\Model\File\Uploader::TMP_NAME_EMPTY) {
$this->_logger->critical($e);
}
}
return $this;
}
}5. Then, display the product attachment link and delete the checkbox after saving the product in the admin form. For that create a di.xml in app/code/Milople/ProductAttachment/etc/adminhtml
<?xml version="1.0"?>
<config xmlns:xsi="http://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" type="Magento\Ui\DataProvider\Modifier\Pool">
<arguments>
<argument name="modifiers" xsi:type="array">
<item name="attachment" xsi:type="array">
<item name="class" xsi:type="string">Milople\ProductAttachment\Ui\DataProvider\Product\Form\Modifier\File</item>
<item name="sortOrder" xsi:type="number">1000</item>
</item>
</argument>
</arguments>
</virtualType>
</config>6. Then, create File.php in app/code/Milople/ProductAttachment/Ui/DataProvider/Product/Form/Modifier
<?php
namespace Milople\ProductAttachment\Ui\DataProvider\Product\Form\Modifier;
use Magento\Framework\Stdlib\ArrayManager;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier;
class File extends AbstractModifier
{
/**
* @var ArrayManager
*/
protected $arrayManager;
/**
* @var StoreManagerInterface
*/
protected $storeManager;
/**
* @param ArrayManager $arrayManager
* @param StoreManagerInterface $storeManager
*/
public function __construct(
ArrayManager $arrayManager,
StoreManagerInterface $storeManager
) {
$this->arrayManager = $arrayManager;
$this->storeManager = $storeManager;
}
public function modifyMeta(array $meta)
{
$fieldCode = 'attachment';
$elementPath = $this->arrayManager->findPath($fieldCode, $meta, null, 'children');
$containerPath = $this->arrayManager->findPath(static::CONTAINER_PREFIX . $fieldCode, $meta, null, 'children');
if (!$elementPath) {
return $meta;
}
$mediaUrl = $this->storeManager->getStore()
->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
$meta = $this->arrayManager->merge(
$containerPath,
$meta,
[
'children' => [
$fieldCode => [
'arguments' => [
'data' => [
'config' => [
'elementTmpl' => 'Milople_ProductAttachment/elements/file',
'media_url' => $mediaUrl
],
],
],
]
]
]
);
return $meta;
}
public function modifyData(array $data)
{
return $data;
}
}7. create file.html in app/code/Milople/ProductAttachment/view/adminhtml/web/template/elements
<input class="admin__control-file" type="file" data-bind="
hasFocus: focused,
attr: {
name: inputName,
placeholder: placeholder,
'aria-describedby': noticeId,
id: uid,
disabled: disabled,
form: formId
}"
/>
<!-- ko if: $parent.source.data.product[code] -->
<span>
<a attr="href: media_url+'catalog/product/attachment/'+$parent.source.data.product[code]" text="$parent.source.data.product[code]" target="_blank"></a>
<label attr="for: uid+'_delete'">
<input type="checkbox" attr="name: 'product['+code + '_delete]', id: uid+'_delete', form: formId">
<span data-bind="i18n:'Delete'"></span>
</label>
</span>
<!-- /ko -->And you’re done! Save details and check on the front end. If you come across any errors or need some clarification feel free to drop me a line. Happy to help – Always.
Solved? Click KUDOS and accept it as a solution.
Thank
The solution worked for me thanks to the community and the members for the solution. PaybyPlateMa Login
Hi @lennyburkdc1c9,
Greetings!
Please click KUDOS or accept it as a solution so that it can help others too.
Thanks