How to create multiple insert image field in ui form like product form gallery

How to create multiple insert image field in ui form like product form gallery

Hello, usign this blog you can create multiple insert image field like product media gallery

=> first of all add below code in you ui component form

     <‍htmlContent name="admin_gallery" sortOrder="22">
        <‍argument name="data" xsi:type="array">
            <‍item name="wrapper" xsi:type="array">
                <‍item name="label" xsi:type="string" translate="true">Admin Gallery Images<‍/item>
                <‍item name="collapsible" xsi:type="boolean">true<‍/item>
                <‍item name="opened" xsi:type="boolean">false<‍/item>
            <‍/item>
        <‍/argument>
        <‍settings>
            <‍wrapper>
                <‍canShow>true<‍/canShow>
                <‍componentType>fieldset<‍/componentType>
            <‍/wrapper>
        <‍/settings>
        <‍block name="admin_gallery" class="Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Gallery">
            <‍block class="Watchcentre\AdminImages\Block\Adminhtml\Gallery\Content" as="content">
                <‍arguments>
                    <‍argument name="config" xsi:type="array">
                        <‍item name="parentComponent" xsi:type="string">product_form.product_form.block_admin_gallery.block_admin_gallery<‍/item>
                    <‍/argument>
                <‍/arguments>
            <‍/block>
        <‍/block>
    <‍/htmlContent>       

=> now, create Content.php at Tridhya\AdminImages\Block\Adminhtml\Gallery\Content

	namespace Tridhya\AdminImages\Block\Adminhtml\Gallery;

	use Magento\Backend\Block\Media\Uploader;
	use Magento\Framework\View\Element\AbstractBlock;
	use Magento\Framework\App\ObjectManager;
	use Magento\Framework\Json\Helper\Data as JsonHelper;
	use Magento\Framework\App\Filesystem\DirectoryList;
	use Magento\Framework\Exception\FileSystemException;
	use Magento\Backend\Block\DataProviders\ImageUploadConfig as ImageUploadConfigDataProvider;
	use Magento\MediaStorage\Helper\File\Storage\Database;
	use Magento\Framework\Serialize\Serializer\Json;

	class Content extends \Magento\Backend\Block\Widget
	{
	    protected $_template = 'Tridhya_AdminImages::gallery.phtml';

	    protected $_mediaConfig;
	    protected $_jsonEncoder;
	    protected $imagesFactory;
	    protected $_jsonFramework;
	    protected $request;
	    private $imageHelper;
	    private $imageUploadConfigDataProvider;
	    private $fileStorageDatabase;

	    public function __construct(
	        \Magento\Backend\Block\Template\Context $context,
	        \Magento\Framework\Json\EncoderInterface $jsonEncoder,
	        \Tridhya\AdminImages\Model\Media\Config $mediaConfig,
	        \Magento\Framework\Registry $coreRegister,
	        \Magento\Framework\App\RequestInterface $request,
	        \Magento\Framework\ObjectManagerInterface $objectManager,
	        \Tridhya\AdminImages\Model\ImagesFactory $imagesFactory,
	        Json $jsonFramework,
	        array $data = [],
	        ImageUploadConfigDataProvider $imageUploadConfigDataProvider = null,
	        Database $fileStorageDatabase = null,
	        ?JsonHelper $jsonHelper = null
	    ) {

	        $this->_jsonEncoder = $jsonEncoder;
	        $this->_mediaConfig = $mediaConfig;
	        $this->_coreRegister = $coreRegister;
	        $this->imagesFactory = $imagesFactory;
	        $this->request = $request;
	        $this->_jsonFramework = $jsonFramework;
	        $data['jsonHelper'] = $jsonHelper ?? ObjectManager::getInstance()->get(JsonHelper::class);
	        $this->imageUploadConfigDataProvider = $imageUploadConfigDataProvider
	            ?: ObjectManager::getInstance()->get(ImageUploadConfigDataProvider::class);
	        $this->fileStorageDatabase = $fileStorageDatabase
	            ?: ObjectManager::getInstance()->get(Database::class);
	        parent::__construct($context, $data);
	    }

	    /**
	     * @return AbstractBlock
	     */

	    protected function _prepareLayout()
	    {
	        $this->addChild(
	            'uploader',
	            \Magento\Backend\Block\Media\Uploader::class,
	            ['image_upload_config_data' => $this->imageUploadConfigDataProvider]
	        );

	        $this->getUploader()->getConfig()->setUrl(
	            $this->_urlBuilder->getUrl('adminimages/image/upload')
	        )->setFileField(
	            'internal_images'
	        )->setFilters(
	            [
	                'images' => [
	                    'label' => __('Images (.gif, .jpg, .png)'),
	                    'files' => ['*.gif', '*.jpg', '*.jpeg', '*.png'],
	                ],
	            ]
	        );

	        return parent::_prepareLayout();
	    }

	    public function getUploader()
	    {
	        return $this->getChildBlock('uploader');
	    }

	    /**
	     * Retrieve uploader block html
	     *
	     * @return string
	     */
	    public function getUploaderHtml()
	    {
	        return $this->getChildHtml('uploader');
	    }

	    /**
	     * @return string
	     */
	    public function getJsObjectName()
	    {
	        return $this->getHtmlId() . 'JsObject';
	    }

	    /**
	     * @return string
	     */
	    public function getAddImagesButton()
	    {
	        return $this->getButtonHtml(
	            __('Add New Images'),
	            $this->getJsObjectName() . '.showUploader()',
	            'add',
	            $this->getHtmlId() . '_add_images_button'
	        );
	    }

	    public function getImagesJson()
	    {
	        $productId = $this->request->getParam('id');
	        $collection = $this->imagesFactory->create()->getCollection()->addFieldToFilter('product_id', $productId);
	        $item = $collection->getFirstItem();
	        $internalImages = $item->getInternalImages();

	        if ($internalImages)
	        {
	            $imgArray = $this->_jsonFramework->unserialize($internalImages);
	            $mediaDir = $this->_filesystem->getDirectoryRead(DirectoryList::MEDIA);
	            $images = $this->sortImagesByPosition($imgArray);
	            foreach ($images as &$image) {
	                $image['url'] = $this->_mediaConfig->getMediaUrl($image['file']);
	                if ($this->fileStorageDatabase->checkDbUsage() &&
	                    !$mediaDir->isFile($this->_mediaConfig->getMediaPath($image['file']))
	                ) {
	                    $this->fileStorageDatabase->saveFileToFilesystem(
	                        $this->_mediaConfig->getMediaPath($image['file'])
	                    );
	                }
	                try {
	                    $fileHandler = $mediaDir->stat($this->_mediaConfig->getMediaPath($image['file']));
	                    $image['size'] = $fileHandler['size'];
	                    $image['media_type'] = "image";
	                    $image['entity_id'] = $productId;
	                    $image['label'] = "Image";
	                    $image['label_default'] = "Image";
	                    $image['position_default'] = $image['position'];
	                } catch (FileSystemException $e) {
	                    $image['url'] = $this->getImageHelper()->getDefaultPlaceholderUrl('small_image');
	                    $image['size'] = 0;
	                    $this->_logger->warning($e);
	                }
	            }
	            return $this->_jsonEncoder->encode($images);
	        }
	        return '[]';
	    }

	    private function sortImagesByPosition($images)
	    {
	        $nullPositions = [];
	        foreach ($images as $index => $image) {
	            if ($image['position'] === null) {
	                $nullPositions[] = $image;
	                unset($images[$index]);
	            }
	        }
	        if (is_array($images) && !empty($images)) {
	            usort(
	                $images,
	                function ($imageA, $imageB) {
	                    return ($imageA['position'] < $imageB['position']) ? -1 : 1;
	                }
	            );
	        }
	        return array_merge($images, $nullPositions);
	    }

	    /**
	     * Retrieve media attributes
	     *
	     * @return array
	     */
	    public function getMediaAttributes()
	    {
	        return $this->getElement()->getDataObject()->getMediaAttributes();
	    }

	    /**
	     * @return string
	     */
	    public function getImagesValuesJson()
	    {
	        $values = [];
	        foreach ($this->getMediaAttributes() as $attribute) {
	            /* @var $attribute \Magento\Eav\Model\Entity\Attribute */
	            $values[$attribute->getAttributeCode()] = $this->getElement()->getDataObject()->getData(
	                $attribute->getAttributeCode()
	            );
	        }
	        return $this->_jsonEncoder->encode($values);
	    }

	    public function hasUseDefault()
	    {
	        foreach ($this->getMediaAttributes() as $attribute) {
	            if ($this->getElement()->canDisplayUseDefault($attribute)) {
	                return true;
	            }
	        }

	        return false;
	    }

	    private function getImageHelper()
	    {
	        if ($this->imageHelper === null) {
	            $this->imageHelper = \Magento\Framework\App\ObjectManager::getInstance()
	                ->get(\Magento\Catalog\Helper\Image::class);
	        }
	        return $this->imageHelper;
	    }
	}

=> now create Config.php at Tridhya\AdminImages\Model\Media

	namespace Tridhya\AdminImages\Model\Media;

	use Tridhya\AdminImages\Api\Data\ConfigInterface;

	class Config implements ConfigInterface
	{

	    protected $storeManager;
	    /**
	     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
	     */
	    public function __construct(\Magento\Store\Model\StoreManagerInterface $storeManager)
	    {
	        $this->storeManager = $storeManager;
	    }

	    /**
	     * Filesystem directory path of product images
	     * relatively to media folder
	     *
	     * @return string
	     */
	    public function getBaseMediaPathAddition()
	    {
	        return 'catalog/admin';
	    }

	    /**
	     * Web-based directory path of product images
	     * relatively to media folder
	     *
	     * @return string
	     */
	    public function getBaseMediaUrlAddition()
	    {
	        return 'catalog/admin';
	    }

	    /**
	     * @return string
	     */
	    public function getBaseMediaPath()
	    {
	        return 'catalog/admin';
	    }

	    /**
	     * @return string
	     */
	    public function getBaseMediaUrl()
	    {
	        return $this->storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/admin';
	    }

	    /**
	     * Filesystem directory path of temporary product images
	     * relatively to media folder
	     *
	     * @return string
	     */
	    public function getBaseTmpMediaPath()
	    {
	        return   $this->getBaseMediaPathAddition();
	    }

	    /**
	     * @return string
	     */
	    public function getBaseTmpMediaUrl()
	    {
	        return $this->storeManager->getStore()->getBaseUrl(
	            \Magento\Framework\UrlInterface::URL_TYPE_MEDIA
	        )  . $this->getBaseMediaUrlAddition();
	    }

	    /**
	     * @param string $file
	     * @return string
	     */
	    public function getMediaUrl($file)
	    {
	        return $this->getBaseMediaUrl() . '/' . $this->_prepareFile($file);
	    }

	    /**
	     * @param string $file
	     * @return string
	     */
	    public function getMediaPath($file)
	    {
	        return $this->getBaseMediaPath() . '/' . $this->_prepareFile($file);
	    }

	    /**
	     * @param string $file
	     * @return string
	     */
	    public function getTmpMediaUrl($file)
	    {
	        return $this->getBaseTmpMediaUrl() . '/' . $this->_prepareFile($file);
	    }

	    /**
	     * Part of URL of temporary product images
	     * relatively to media folder
	     *
	     * @param string $file
	     * @return string
	     */
	    public function getTmpMediaShortUrl($file)
	    {
	        return $this->getBaseMediaUrlAddition() . '/' . $this->_prepareFile($file);
	    }

	    /**
	     * Part of URL of product images relatively to media folder
	     *
	     * @param string $file
	     * @return string
	     */
	    public function getMediaShortUrl($file)
	    {
	        return $this->getBaseMediaUrlAddition() . '/' . $this->_prepareFile($file);
	    }

	    /**
	     * @param string $file
	     * @return string
	     */
	    public function getTmpMediaPath($file)
	    {
	        return $this->getBaseTmpMediaPath() . '/' . $this->_prepareFile($file);
	    }

	    /**
	     * @param string $file
	     * @return string
	     */
	    protected function _prepareFile($file)
	    {
	        return ltrim(str_replace('\\', '/', $file), '/');

	    }
	}



=> create ConfigInterface.php at Tridhya\AdminImages\Api\Data

	namespace Tridhya\AdminImages\Api\Data;
	 
	interface ConfigInterface
	{
	    /**
	     * Retrieve base url for media files
	     *
	     * @return string
	     */
	    public function getBaseMediaUrl();

	    /**
	     * Retrieve base path for media files
	     *
	     * @return string
	     */
	    public function getBaseMediaPath();

	    /**
	     * Retrieve url for media file
	     *
	     * @param  string $file
	     * @return string
	     */
	    public function getMediaUrl($file);

	    /**
	     * Retrieve file system path for media file
	     *
	     * @param  string $file
	     * @return string
	     */


	    public function getMediaPath($file);
	}



=> now, create di.xml at Tridhya\AdminImages\etc



	<‍?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="Watchcentre\AdminImages\AdminImagesUpload" type="Watchcentre\AdminImages\Model\ImageUploader">
	        <‍arguments>
	            <‍argument name="baseTmpPath" xsi:type="string">catalog/admin/tmp<‍/argument>
	            <‍argument name="basePath" xsi:type="string">catalog/admin<‍/argument>
	            <‍argument name="allowedExtensions" xsi:type="array">
	                <‍item name="jpg" xsi:type="string">jpg<‍/item>
	                <‍item name="jpeg" xsi:type="string">jpeg<‍/item>
	                <‍item name="gif" xsi:type="string">gif<‍/item>
	                <‍item name="png" xsi:type="string">png<‍/item>
	            <‍/argument>
	            <‍argument name="allowedMimeTypes" xsi:type="array">
	                <‍item name="jpg" xsi:type="string">image/jpg<‍/item>
	                <‍item name="jpeg" xsi:type="string">image/jpeg<‍/item>
	                <‍item name="gif" xsi:type="string">image/gif<‍/item>
	                <‍item name="png" xsi:type="string">image/png<‍/item>
	            <‍/argument>
	        <‍/arguments>
	    <‍/virtualType>
	    <‍type name="Watchcentre\AdminImages\Controller\Adminhtml\Image\Upload">
	        <‍arguments>
	            <‍argument name="imageUploader" xsi:type="object">Watchcentre\AdminImages\AdminImagesUpload<‍/argument>
	        <‍/arguments>
	    <‍/type>
	<‍/config>



=> create ImageUploader.php at Tridhya\AdminImages\Model



	namespace Tridhya\AdminImages\Model;

	class ImageUploader
	{
	    protected $coreFileStorageDatabase;
	    protected $mediaDirectory;
	    private $uploaderFactory;
	    protected $storeManager;
	    protected $logger;
	    protected $baseTmpPath;
	    protected $basePath;
	    protected $allowedExtensions;

	    public function __construct(
	        \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDatabase,
	        \Magento\Framework\Filesystem $filesystem,
	        \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory,
	        \Magento\Store\Model\StoreManagerInterface $storeManager,
	        \Psr\Log\LoggerInterface $logger,
	        $baseTmpPath,
	        $basePath,
	        $allowedExtensions
	    ) {
	        $this->coreFileStorageDatabase = $coreFileStorageDatabase;
	        $this->mediaDirectory = $filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA);
	        $this->uploaderFactory = $uploaderFactory;
	        $this->storeManager = $storeManager;
	        $this->logger = $logger;
	        $this->baseTmpPath = $baseTmpPath;
	        $this->basePath = $basePath;
	        $this->allowedExtensions = $allowedExtensions;
	    }

	    public function setBaseTmpPath($baseTmpPath)
	    {
	        $this->baseTmpPath = $baseTmpPath;
	    }

	    public function setBasePath($basePath)
	    {
	        $this->basePath = $basePath;
	    }

	    public function setAllowedExtensions($allowedExtensions)
	    {
	        $this->allowedExtensions = $allowedExtensions;
	    }

	    public function getBaseTmpPath()
	    {
	        return $this->baseTmpPath;
	    }

	    public function getBasePath()
	    {
	        return $this->basePath;
	    }

	    public function getAllowedExtensions()
	    {
	        return $this->allowedExtensions;
	    }

	    public function getFilePath($path, $imageName)
	    {
	        return rtrim($path, '/') . '/' . ltrim($imageName, '/');
	    }

	    public function moveFileFromTmp($imageName)
	    {
	        $baseTmpPath = $this->getBaseTmpPath();
	        $basePath = $this->getBasePath();

	        $baseImagePath = $this->getFilePath($basePath, $imageName);
	        $baseTmpImagePath = $this->getFilePath($baseTmpPath, $imageName);

	        try {
	            $this->coreFileStorageDatabase->copyFile(
	                $baseTmpImagePath,
	                $baseImagePath
	            );
	            $this->mediaDirectory->renameFile(
	                $baseTmpImagePath,
	                $baseImagePath
	            );
	        } catch (\Exception $e) {
	            throw new \Magento\Framework\Exception\LocalizedException(
	                __('Something went wrong while saving the file(s).')
	            );
	        }

	        return $imageName;
	    }

	    public function saveFileToTmpDir($fileId)
	    {
	        $baseTmpPath = $this->getBaseTmpPath();

	        $uploader = $this->uploaderFactory->create(['fileId' => $fileId]);
	        $uploader->setAllowedExtensions($this->getAllowedExtensions());
	        $uploader->setAllowRenameFiles(true);

	        $result = $uploader->save($this->mediaDirectory->getAbsolutePath($baseTmpPath));

	        if (!$result) {
	            throw new \Magento\Framework\Exception\LocalizedException(
	                __('File can not be saved to the destination folder.')
	            );
	        }

	        $result['tmp_name'] = str_replace('\ ', '/', $result['tmp_name']);
	        $result['path'] = str_replace('\ ', '/', $result['path']);
	        $result['url'] = $this->storeManager
	                ->getStore()
	                ->getBaseUrl(
	                    \Magento\Framework\UrlInterface::URL_TYPE_MEDIA
	                ) . $this->getFilePath($baseTmpPath, $result['file']);
	        $result['name'] = $result['file'];

	        if (isset($result['file'])) {
	            try {
	                $relativePath = rtrim($baseTmpPath, '/') . '/' . ltrim($result['file'], '/');
	                $this->coreFileStorageDatabase->saveFile($relativePath);
	            } 
	            catch (\Exception $e) {
	                $this->logger->critical($e);
	                throw new \Magento\Framework\Exception\LocalizedException(
	                    __('Something went wrong while saving the file(s).')
	                );
	            }
	        }

	        return $result;
	    }
	}



=> for upload file at file path using ajax create Upload.php at Tridhya\AdminImages\Controller\Adminhtml\Image



	namespace Tridhya\AdminImages\Controller\Adminhtml\Image;

	use Magento\Framework\Controller\ResultFactory;

	class Upload extends \Magento\Backend\App\Action
	{
	    protected $imageUploader;
	    protected $resultRawFactory;

	    public function __construct(
	        \Magento\Backend\App\Action\Context $context,
	        \Magento\Framework\Controller\Result\RawFactory $resultRawFactory,
	        \Tridhya\AdminImages\Model\ImageUploader $imageUploader
	    ) {
	        parent::__construct($context);
	        $this->resultRawFactory = $resultRawFactory;
	        $this->imageUploader = $imageUploader;
	    }

	    public function execute()
	    {
	        try {
	            $imageId = $this->_request->getParam('param_name', 'internal_images');
	            $result = $this->imageUploader->saveFileToTmpDir($imageId);

	            $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);
	    }
	}



=> create requirejs-config.js at Tridhya\AdminImages\view\adminhtml



	var config = {
	    map: {
	        '*': {
	            adminImageGallery: 'Tridhya_AdminImages/js/image-gallery'
	        }
	    }
	};



=> create gallery.phtml at Tridhya\AdminImages\view\adminhtml\templates



	
	$elementName = $block->getElement()->getName() . '[internal_images]';
	$formName = $block->getFormName();
	/** @var \Magento\Framework\Json\Helper\Data $jsonHelper */
	$jsonHelper = $block->getData('jsonHelper');
	$null = null;
	?>
	<‍div id="getHtmlId() ?>"
	     class="gallery"
	     data-mage-init='{"adminImageGallery":{"template":"#getHtmlId() ?>-template"}}'
	     data-parent-component="escapeHtml($block->getData('config/parentComponent')) ?>"
	     data-images="escapeHtml($block->getImagesJson()) ?>"
	     data-types="escapeHtml($null) ?>">

		getElement()->getReadonly()) {?>
	        <‍div class="image image-placeholder">
	            getUploaderHtml() ?>
	            <‍div class="product-image-wrapper">
	                <‍p class="image-placeholder-text">
	                    escapeHtml(__('Browse to find or drag image here')) ?>
	                <‍/p>
	            <‍/div>
	        <‍/div>
	    

	    <‍script id="getHtmlId() ?>-template" type="text/x-magento-template">
	        <‍div class="image item<% if (data.disabled == 1) { %> hidden-for-front<% } %>"
	             data-role="image">
	            <‍input type="hidden"
	                   name="escapeHtmlAttr($elementName) ?>[<%- data.file_id %>][position]"
	                   value="<%- data.position %>"
	                   data-form-part="escapeHtmlAttr($formName) ?>"
	                   class="position"/>
	            <‍input type="hidden"
	                   name="escapeHtmlAttr($elementName) ?>[<%- data.file_id %>][file]"
	                   data-form-part="escapeHtmlAttr($formName) ?>"
	                   value="<%- data.file %>"/>
	            <‍input type="hidden"
	                   name="escapeHtmlAttr($elementName) ?>[<%- data.file_id %>][value_id]"
	                   data-form-part="escapeHtmlAttr($formName) ?>"
	                   value="<%- data.value_id %>"/>
	            <‍input type="hidden"
	                   name="escapeHtmlAttr($elementName) ?>[<%- data.file_id %>][label]"
	                   data-form-part="escapeHtmlAttr($formName) ?>"
	                   value="<%- data.label %>"/>
	            <‍input type="hidden"
	                   name="escapeHtmlAttr($elementName) ?>[<%- data.file_id %>][disabled]"
	                   data-form-part="escapeHtmlAttr($formName) ?>"
	                   value="<%- data.disabled %>"/>
	            <‍input type="hidden"
	                   name="escapeHtmlAttr($elementName) ?>[<%- data.file_id %>][media_type]"
	                   data-form-part="escapeHtmlAttr($formName) ?>"
	                   value="image"/>
	            <‍input type="hidden"
	                   name="escapeHtmlAttr($elementName) ?>[<%- data.file_id %>][removed]"
	                   data-form-part="escapeHtmlAttr($formName) ?>"
	                   value=""
	                   class="is-removed"/>

	            <‍div class="product-image-wrapper">
	                <‍img class="product-image"
	                     data-role="image-element"
	                     src="<%- data.url %>"
	                     alt="<%- data.label %>"/>

	                <‍div class="actions">
	                    <‍button type="button"
	                            class="action-remove"
	                            data-role="delete-button"
	                            title="escapeHtmlAttr(__('Delete image')) ?>">
	                    <‍span>
	                        escapeHtml(__('Delete image')) ?>
	                    <‍/span>
	                    <‍/button>
	                    <‍div class="draggable-handle"><‍/div>
	                <‍/div>
	                <‍div class="image-fade"><‍span>escapeHtml(__('Hidden')) ?><‍/span><‍/div>
	            <‍/div>

	            <‍div class="item-description">
	                <‍div class="item-title" data-role="img-title"><%- data.label %><‍/div>
	                <‍div class="item-size">
	                    <‍span data-role="image-dimens"><‍/span>, <‍span data-role="image-size"><%- data.sizeLabel %><‍/span>
	                <‍/div>
	            <‍/div>
	        <‍/div>
	    <‍/script>
	<‍/div>



=> create image-gallery.js at Tridhya\AdminImages\view\adminhtml\web\js\



define([
    'jquery',
    'underscore',
    'mage/template',
    'uiRegistry',
    'jquery/ui',
    'baseImage'
], function ($, _, mageTemplate, registry) {
    'use strict';

    /**
     * Formats incoming bytes value to a readable format.
     *
     * @param {Number} bytes
     * @returns {String}
     */
    function bytesToSize(bytes) {
        var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'],
            i;

        if (bytes === 0) {
            return '0 Byte';
        }

        i = window.parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));

        return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
    }

    /**
     * Product gallery widget
     */
    $.widget('mage.adminImageGallery', {
        options: {
            imageSelector: '[data-role=image]',
            imageElementSelector: '[data-role=image-element]',
            template: '[data-template=image]',
            imageResolutionLabel: '[data-role=resolution]',
            imgTitleSelector: '[data-role=img-title]',
            imageSizeLabel: '[data-role=size]',
            types: null,
            initialized: false
        },

        /**
         * Gallery creation
         * @protected
         */
        _create: function () {
            this.options.types = this.options.types || this.element.data('types');
            this.options.images = this.options.images || this.element.data('images');
            this.options.parentComponent = this.options.parentComponent || this.element.data('parent-component');

            this.imgTmpl = mageTemplate(this.element.find(this.options.template).html().trim());

            this._bind();
           
            $.each(this.options.images, $.proxy(function (index, imageData) {
                this.element.trigger('addItem', imageData);
            }, this));

            this.options.initialized = true;
        },

        /**
         * Bind handler to elements
         * @protected
         */
        _bind: function () {
            this._on({
                updateImageTitle: '_updateImageTitle',
                updateVisibility: '_updateVisibility',
                addItem: '_addItem',
                removeItem: '_removeItem',
                setPosition: '_setPosition',
                resort: '_resort',

                /**
                 * @param {jQuery.Event} event
                 */
                'mouseup [data-role=delete-button]': function (event) {
                    var $imageContainer;

                    event.preventDefault();
                    $imageContainer = $(event.currentTarget).closest(this.options.imageSelector);
                    this.element.find('[data-role=dialog]').trigger('close');
                    this.element.trigger('removeItem', $imageContainer.data('imageData'));
                },

                /**
                 * @param {jQuery.Event} event
                 */
                'mouseup [data-role=make-base-button]': function (event) {
                    var $imageContainer,
                        imageData;

                    event.preventDefault();
                    event.stopImmediatePropagation();
                    $imageContainer = $(event.currentTarget).closest(this.options.imageSelector);
                    imageData = $imageContainer.data('imageData');
                    // this.setBase(imageData);
                }
            });

            this.element.sortable({
                distance: 8,
                items: this.options.imageSelector,
                tolerance: 'pointer',
                cancel: 'input, button, .uploader',
                update: $.proxy(function () {
                    this.element.trigger('resort');
                }, this)
            });
        },

        /**
         * Find element by fileName
         * @param {Object} data
         * @returns {Element}
         */
        findElement: function (data) {
            return this.element.find(this.options.imageSelector).filter(function () {
                return $(this).data('imageData').file === data.file;
            }).first();
        },

        /**
         * Mark parent fieldset that content was updated
         */
        _contentUpdated: function () {
            if (this.options.initialized && this.options.parentComponent) {
                registry.async(this.options.parentComponent)(
                    function (parentComponent) {
                        parentComponent.bubble('update', true);
                    }
                );
            }
        },

        /**
         * Add image
         * @param {jQuery.Event} event
         * @param {Object} imageData
         * @private
         */
        _addItem: function (event, imageData) {
            var count = this.element.find(this.options.imageSelector).length,
                element,
                imgElement,
                position = count + 1,
                lastElement = this.element.find(this.options.imageSelector + ':last');

            if (lastElement.length === 1) {
                position = parseInt(lastElement.data('imageData').position || count, 10) + 1;
            }
            imageData = $.extend({
                'file_id': imageData['value_id'] ? imageData['value_id'] : Math.random().toString(33).substr(2, 18),
                'disabled': imageData.disabled ? imageData.disabled : 0,
                'position': position,
                sizeLabel: bytesToSize(imageData.size)
            }, imageData);

            element = this.imgTmpl({
                data: imageData
            });

            element = $(element).data('imageData', imageData);

            if (count === 0) {
                element.prependTo(this.element);
            } else {
                element.insertAfter(lastElement);
            }

            if (!this.options.initialized &&
                this.options.images.length === 0 ||
                this.options.initialized &&
                this.element.find(this.options.imageSelector + ':not(.removed)').length === 1
            ) {
                // this.setBase(imageData);
            }

            imgElement = element.find(this.options.imageElementSelector);

            imgElement.on('load', this._updateImageDimesions.bind(this, element));

            this._contentUpdated();
        },

        /**
         * Returns a list of current images.
         *
         * @returns {jQueryCollection}
         */
        _getImages: function () {
            return this.element.find(this.options.imageSelector);
        },

        _updateImageDimesions: function (imgContainer) {
            var $img = imgContainer.find(this.options.imageElementSelector)[0],
                $dimens = imgContainer.find('[data-role=image-dimens]');

            $dimens.text($img.naturalWidth + 'x' + $img.naturalHeight + ' px');
        },

        /**
         *
         * @param {jQuery.Event} event
         * @param {Object} data
         */
        _updateImageTitle: function (event, data) {
            var imageData = data.imageData,
                $imgContainer = this.findElement(imageData),
                $title = $imgContainer.find(this.options.imgTitleSelector),
                value;

            value = imageData['media_type'] === 'external-video' ?
                imageData['video_title'] :
                imageData.label;

            $title.text(value);

            this._contentUpdated();
        },

        /**
         * Remove Image
         * @param {jQuery.Event} event
         * @param {Object} imageData
         * @private
         */
        _removeItem: function (event, imageData) {
            var $imageContainer = this.findElement(imageData);

            imageData.isRemoved = true;
            $imageContainer.addClass('removed').hide().find('.is-removed').val(1);

            this._contentUpdated();
        },

        /**
         * Set image type
         * @param {jQuery.Event} event
         * @param {Obejct} data
         * @private
         */
        _setImageType: function (event, data) {
            if (data.type === 'image') {
                this.element.find('.base-image').removeClass('base-image');
            }

            if (data.imageData) {
                this.options.types[data.type].value = data.imageData.file;

                if (data.type === 'image') {
                    this.findElement(data.imageData).addClass('base-image');
                }
            } else {
                this.options.types[data.type].value = 'no_selection';
            }
            this.element.find('.image-' + data.type).val(this.options.types[data.type].value || 'no_selection');
            // this._updateImagesRoles();
            this._contentUpdated();
        },

        /**
         * Resort images
         * @private
         */
        _resort: function () {
            this.element.find('.position').each($.proxy(function (index, element) {
                var value = $(element).val();

                if (value != index) { //eslint-disable-line eqeqeq
                    this.element.trigger('moveElement', {
                        imageData: $(element).closest(this.options.imageSelector).data('imageData'),
                        position: index
                    });
                    $(element).val(index);
                }
            }, this));

            this._contentUpdated();
        },

        /**
         * Set image position
         * @param {jQuery.Event} event
         * @param {Object} data
         * @private
         */
        _setPosition: function (event, data) {
            var $element = this.findElement(data.imageData),
                curIndex = this.element.find(this.options.imageSelector).index($element),
                newPosition = data.position + (curIndex > data.position ? -1 : 0);

            if (data.position != curIndex) { //eslint-disable-line eqeqeq
                if (data.position === 0) {
                    this.element.prepend($element);
                } else {
                    $element.insertAfter(
                        this.element.find(this.options.imageSelector).eq(newPosition)
                    );
                }
                this.element.trigger('resort');
            }

            this._contentUpdated();
        }
    });

    // Extension for mage.adminImageGallery - Add advanced settings block
    $.widget('mage.adminImageGallery', $.mage.adminImageGallery, {
        options: {
            dialogTemplate: '[data-role=img-dialog-tmpl]',
            dialogContainerTmpl: '[data-role=img-dialog-container-tmpl]'
        },

        /** @inheritdoc */
        _create: function () {
            var template = this.element.find(this.options.dialogTemplate),
                containerTmpl = this.element.find(this.options.dialogContainerTmpl);

            this._super();
            this.modalPopupInit = false;

            if (template.length) {
                this.dialogTmpl = mageTemplate(template.html().trim());
            }

            if (containerTmpl.length) {
                this.dialogContainerTmpl = mageTemplate(containerTmpl.html().trim());
            } else {
                this.dialogContainerTmpl = mageTemplate('');
            }

            // this._initDialog();
        },

        /**
         * Bind handler to elements
         * @protected
         */
        _bind: function () {
            var events = {};

            this._super();

            events['click [data-role=close-panel]'] = $.proxy(function () {
                this.element.find('[data-role=dialog]').trigger('close');
            }, this);

            /**
             * @param {jQuery.Event} event
             */
            events['click ' + this.options.imageSelector] = function (event) {
                var imageData, $imageContainer;

                if (!$(event.currentTarget).is('.ui-sortable-helper')) {
                    $(event.currentTarget).addClass('active');
                    imageData = $(event.currentTarget).data('imageData');
                    $imageContainer = this.findElement(imageData);

                    if ($imageContainer.is('.removed')) {
                        return;
                    }
                    // this.element.trigger('openDialog', [imageData]);
                }
            };
            this._on(events);
            this.element.on('sortstart', $.proxy(function () {
                this.element.find('[data-role=dialog]').trigger('close');
            }, this));
        },
        
        _updateVisibility: function (event, data) {
            var imageData = data.imageData,
                disabled = +data.disabled,
                $imageContainer = this.findElement(imageData);

            !!disabled ? //eslint-disable-line no-extra-boolean-cast
                $imageContainer.addClass('hidden-for-front') :
                $imageContainer.removeClass('hidden-for-front');

            $imageContainer.find('[name*="disabled"]').val(disabled);
            imageData.disabled = disabled;

            this._contentUpdated();
        }
    });

    return $.mage.adminImageGallery;
});



=> for saving images data in your table



	if(isset($data['internal_images'])){

        $images = $data['internal_images'];
        $this->imageUploader = \Magento\Framework\App\ObjectManager::getInstance()->get(
                'Tridhya\AdminImages\AdminImagesUpload');
        if($images != null)
        {
            foreach($images as $key => $value){
                if (isset($images[$key]['label']) && $images[$key]['label'] == null && $images[$key]['removed'] != 1)
                {
                    $imgNames[$key]['file'] = $images[$key]['file'];
                    $imgNames[$key]['position'] = $images[$key]['position'];
                    $this->imageUploader->moveFileFromTmp($images[$key]['file']);
                } elseif (isset($images[$key]['file']) && $images[$key]['label'] != null && $images[$key]['removed'] != 1) {
                    $imgNames[$key]['file'] = $images[$key]['file'];
                    $imgNames[$key]['position'] = $images[$key]['position'];
                } elseif($images[$key]['removed'] != 1) {
                    $imgNames[] = null;
                }
            }
        }
    }

    $jsonArray = $this->_jsonFramework->serialize($imgNames);


Copyright © 2024 Tridhya Tech Limited, Inc. All rights reserved.