8

I have magento2 admin custom module with image upload functionality. I want to upload image from admin. what code should apply for display image field in from, upload image, also image display in edit action.

Thanks

File Path : app\code\[Vendor]\[Module]\Block\Adminhtml\Emp\Edit\Tab\Main.php

    /**
     * Prepare form
     *
     * @return $this
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
    */
    protected function _prepareForm()
    {
        $model = $this->_coreRegistry->registry('emp_post');

        $isElementDisabled = false;

        /** @var \Magento\Framework\Data\Form $form */
        $form = $this->_formFactory->create();

        $form->setHtmlIdPrefix('page_');

        $fieldset = $form->addFieldset('base_fieldset', ['legend' => __('Employee Information')]);

        if ($model->getId()) {
            $fieldset->addField('customer_id', 'hidden', ['name' => 'customer_id']);
        }

        $fieldset->addField(
            'firstname',
            'text',
            [
                'name' => 'firstname',
                'label' => __('First Name'),
                'title' => __('First Name'),
                'required' => true,
                'disabled' => $isElementDisabled,
                'value' =>'abc'
            ]
        );

        $fieldset->addField(
            'lastname',
            'text',
            [
                'name' => 'lastname',
                'label' => __('Last Name'),
                'title' => __('Last Name'),
                'required' => true,
                'disabled' => $isElementDisabled,
                'value' =>'abc'
            ]
        );

        $fieldset->addField(
            'email',
            'text',
            [
                'name' => 'email',
                'label' => __('Email Address'),
                'title' => __('Email Address'),
                'required' => true,
                'disabled' => $isElementDisabled,
                'value' =>'abc'
            ]
        );


        $fieldset->addField(
            'image',
            'image',
            array(
                'name' => 'image',
                'label' => __('Image'),
                'title' => __('Image')
            )
        );

        $fieldset->addField(
            'telephone',
            'text',
            [
                'name' => 'telephone',
                'label' => __('Telephone'),
                'title' => __('Telephone'),
                'required' => true,
                'disabled' => $isElementDisabled,
                'value' =>'abc'
            ]
        );

        $dateFormat = $this->_localeDate->getDateFormat(
            \IntlDateFormatter::SHORT
        );

        $fieldset->addField(
            'dob',
            'date',
            [
                'name' => 'dob',
                'label' => __('Date of birth'),
                'date_format' => $dateFormat,
                'disabled' => $isElementDisabled,
                'class' => 'validate-date validate-date-range date-range-custom_theme-from'
            ]
        );

        $fieldset->addField(
            'is_active',
            'select',
            [
                'label' => __('Status'),
                'title' => __('Status'),
                'name' => 'is_active',
                'required' => true,
                'options' => $this->_status->getOptionArray(),
                'disabled' => $isElementDisabled
            ]
        );
        if (!$model->getId()) {
            $model->setData('is_active', $isElementDisabled ? '0' : '1');
        }


        if($model->getData('image')){
            $model->setData('image','learning/images'.$model->getData('image'));
        }

        $form->setValues($model->getData());
        $this->setForm($form);

        return parent::_prepareForm();
    } 
1

4 Answers 4

18

You need to create a class to handle your image upload field and show the image once is uploaded.

So create [Namespace]\[Module]\Block\Adminhtml\[Entity]\Helper\Image class

<?php
namespace [Namespace]\[Module]\Block\Adminhtml\[Entity]\Helper;
use Magento\Framework\Data\Form\Element\Image as ImageField;
use Magento\Framework\Data\Form\Element\Factory as ElementFactory;
use Magento\Framework\Data\Form\Element\CollectionFactory as ElementCollectionFactory;
use Magento\Framework\Escaper;
use [Namespace]\[Module]\Model\[Entity]\Image as [Entity]Image;
use Magento\Framework\UrlInterface;

/**
 * @method string getValue()
 */
class Image extends ImageField
{
    /**
     * image model
     *
     * @var \[Namespace]\[Module]\Model\[Entity]\Image
     */
    protected $imageModel;

    /**
     * @param [Entity]Image $imageModel
     * @param ElementFactory $factoryElement
     * @param ElementCollectionFactory $factoryCollection
     * @param Escaper $escaper
     * @param UrlInterface $urlBuilder
     * @param array $data
     */
    public function __construct(
        [Entity]Image $imageModel,
        ElementFactory $factoryElement,
        ElementCollectionFactory $factoryCollection,
        Escaper $escaper,
        UrlInterface $urlBuilder,
        $data = []
    )
    {
        $this->imageModel = $imageModel;
        parent::__construct($factoryElement, $factoryCollection, $escaper, $urlBuilder, $data);
    }
    /**
     * Get image preview url
     *
     * @return string
     */
    protected function _getUrl()
    {
        $url = false;
        if ($this->getValue()) {
            $url = $this->imageModel->getBaseUrl().$this->getValue();
        }
        return $url;
    }
}

then create the class that will help you retrieve the image upload path and upload dir

<?php
namespace [Namespace]\[Module]\Model\[Entity];
use Magento\Framework\UrlInterface;
use Magento\Framework\Filesystem;
use Magento\Framework\App\Filesystem\DirectoryList;
class Image
{
    /**
     * media sub folder
     * @var string
     */
    protected $subDir = '[namespace]/[module]/[entity]';
    /**
     * url builder
     *
     * @var \Magento\Framework\UrlInterface
     */
    protected $urlBuilder;
    /**
     * @var \Magento\Framework\Filesystem
     */
    protected $fileSystem;
    /**
     * @param UrlInterface $urlBuilder
     * @param Filesystem $fileSystem
     */
    public function __construct(
        UrlInterface $urlBuilder,
        Filesystem $fileSystem
    )
    {
        $this->urlBuilder = $urlBuilder;
        $this->fileSystem = $fileSystem;
    }
    /**
     * get images base url
     *
     * @return string
     */
    public function getBaseUrl()
    {
        return $this->urlBuilder->getBaseUrl(['_type' => UrlInterface::URL_TYPE_MEDIA]).$this->subDir.'/image';
    }
    /**
     * get base image dir
     *
     * @return string
     */
    public function getBaseDir()
    {
        return $this->fileSystem->getDirectoryWrite(DirectoryList::MEDIA)->getAbsolutePath($this->subDir.'/image');
    }
}

now in your edit for tab add this in the method _prepareForm right after declaring the fieldset

$fieldset->addType('image', '\[Namespace]\[Module]\Block\Adminhtml\[Entity]\Helper\Image');

and add your image field like this

$fieldset->addField(
    'image_field_name',
    'image',
    [
        'name'        => 'image_field_name',
        'label'       => __('Image field Label'),
        'title'       => __('Image field Label'),
    ]
);

In the controller that saves your entity you need to inject in the constructor the following classes

Magento\MediaStorage\Model\File\UploaderFactory and [Namespace]\[Module]\Model\[Entity]\Image

So make your class look like this

<?php
use Magento\Framework\Exception\LocalizedException as FrameworkException;

class ....

protected $uploaderFactory;
protected $imageModel;

public function __construct(
    ....
    \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory,
    \[Namespace]\[Module]\Model\[Entity]\Image $imageModel,
    ....
){
    ...
    $this->uploaderFactory = $uploaderFactory;
    $this->imageModel = $imageModel;
    ...
}

Now, in the same controller add this, before calling $[entity]->save()

$imageName = $this->uploadFileAndGetName('image_field_name', $this->imageModel->getBaseDir(), $data);
$[entity]->setImageFieldName($imageName);

and create this method:

public function uploadFileAndGetName($input, $destinationFolder, $data)
{
    try {
        if (isset($data[$input]['delete'])) {
            return '';
        } else {
            $uploader = $this->uploaderFactory->create(['fileId' => $input]);
            $uploader->setAllowRenameFiles(true);
            $uploader->setFilesDispersion(true);
            $uploader->setAllowCreateFolders(true);
            $result = $uploader->save($destinationFolder);
            return $result['file'];
        }
    } catch (\Exception $e) {
        if ($e->getCode() != \Magento\Framework\File\Uploader::TMP_NAME_EMPTY) {
            throw new FrameworkException($e->getMessage());
        } else {
            if (isset($data[$input]['value'])) {
                return $data[$input]['value'];
            }
        }
    }
    return '';
}

A full example on how to create an entity that supports image and file upload (it's a bit different than described here as it contains an extra class for upload) can be found here

20
  • given url exension not working. it throw error on screen exception 'Magento\Framework\Exception\LocalizedException' with message 'Source class "\Magento\Framework\View\Element\UiComponent\DataProvider\Collection" for "Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory" generation does not exist.' Commented Oct 13, 2015 at 8:48
  • @SHPatel. Clear the contents of var/generation. If this problem persists it can for 2 reasons. You either don't have the latest version of Magento 2 or my extension does not work on the latest version. If the problem is my extension I will check it when I have some time.
    – Marius
    Commented Oct 13, 2015 at 11:11
  • @Marius, How can we display such image into adminhtml Grid section too? Right now is Default magento 2 is showing it for Product Grid. Commented Oct 13, 2015 at 13:29
  • @PrafulRajput. I didn't get to check that part out yet. I have no idea how it's done.
    – Marius
    Commented Oct 13, 2015 at 13:38
  • @marius this works in RC 2. One thing you mention adding $fieldset->addType('image', '[Namespace][Module]\Adminhtml[Entity]\Helper\Image'); I am pretty sure you are missing a "Block" callout. [Namespace][Module]\Block\Adminhtml[Entity]\Helper\Image
    – Eirik
    Commented Nov 9, 2015 at 20:47
3

Admin module for basic add/update news is here. In case you are looking for simple image upload solution look at the following snippet which is taken from the link.

use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Backend\App\Action;
protected $_fileUploaderFactory;
public function __construct(
    \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory,
    Action\Context $context     
) {
    $this->_fileUploaderFactory = $fileUploaderFactory;
    parent::__construct($context);
}
public function execute(){
    $uploader = $this->_fileUploaderFactory->create(['fileId' => 'image']);
    $uploader->setAllowedExtensions(['jpg', 'jpeg', 'gif', 'png']);
    $uploader->setAllowRenameFiles(false);
    $uploader->setFilesDispersion(false);
    $path = $this->_objectManager->get('Magento\Framework\Filesystem')->getDirectoryRead(DirectoryList::MEDIA)
    ->getAbsolutePath('images/');
    $uploader->save($path);
}
4
  • _filesystem not definded :(
    – fudu
    Commented Oct 30, 2018 at 8:48
  • found it, we need to add this to work, also create it in construct() function as well use \Magento\Framework\Filesystem;
    – fudu
    Commented Oct 30, 2018 at 8:57
  • Replace _filesystem by $this->_objectManager->get('Magento\Framework\Filesystem') Commented Apr 15, 2019 at 5:12
  • @divyasekar Can you please answer this question? -> magento.stackexchange.com/questions/287175/… Commented Sep 3, 2019 at 16:45
1

You could add image field in _prepareForm() method of your admin form:

$fieldset->addField(
    'imagefieldname',
    'image',
    array(
        'name' => 'imagefieldname',
        'label' => __('Image'),
        'title' => __('Image')
    )

  );
7
  • 1
    @chanresh image field added done but i need to display image preview on form. Commented Oct 13, 2015 at 8:49
  • 1
    If you upload image and save the record then it will show small thumbnail near "Choose File" input file field. Commented Oct 13, 2015 at 9:08
  • 1
    I have uplode image and save it but thumbnail image can't display. Commented Oct 13, 2015 at 9:27
  • Please add your code snippet for _prepareForm(). Commented Oct 13, 2015 at 12:24
  • check my question, question updated with _prepareForm(). Commented Oct 13, 2015 at 12:36
0

Check the following link for admin custom form image upload

admin custom form image upload magento 2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.