I added the custom checkbox in product image details page.
But, when I check it's not selected and not saved after saving records. I want to do like as Hide from Product Page checkbox working.
Follow this step for checkbox checked and save value in database :
=> Create InstallSchema.php on below path for add custom field in database :
/app/code/CompanyName/ModuleName/Setup
<?php
namespace CompanyName\ModuleName\Setup;
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
class InstallSchema implements InstallSchemaInterface {
public function install(SchemaSetupInterface $setup, ModuleContextInterface $context) {
$installer = $setup;
$installer->startSetup();
/**
* [$tableName catalog_product_option]
* @var [catalog_product_option]
*/
$tableName = $setup->getTable('catalog_product_entity_media_gallery_value');
if ($setup->getConnection()->isTableExists($tableName) == true) {
$columns = [
'displayimage' => [
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
'length' => 5,
'nullable' => false,
'comment' => 'Display Image',
'default' => '0',
],
];
$connection = $setup->getConnection();
foreach ($columns as $name => $definition) {
$connection->addColumn($tableName, $name, $definition);
}
}
$installer->endSetup();
}
}
=> Create events.xml file on this below path for add events catalog_product_save_after
and catalog_product_gallery_prepare_layout
/app/code/CompanyName/ModuleName/etc/adminhtml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="catalog_product_save_after">
<observer name="validate" instance="CompanyName\ModuleName\Observer\ProductSaveAfter" />
</event>
<event name="catalog_product_gallery_prepare_layout">
<observer name="change_template" disabled="true"/>
<observer name="custom_change_template" instance="CompanyName\ModuleName\Observer\ChangeTemplateObserver" />
</event>
</config>
=> Create ChangeTemplateObserver.php file for prepare layout of product gallery :
/app/code/CompanyName/ModuleName/Observer
<?php
namespace CompanyName\ModuleName\Observer;
use Magento\Framework\Event\ObserverInterface;
class ChangeTemplateObserver implements ObserverInterface {
public function execute(\Magento\Framework\Event\Observer $observer) {
$observer->getBlock()->setTemplate('CompanyName_ModuleName::helper/gallery.phtml');
}
}
=> Create gallery.phtml on the below path for make layout of product gallery :
/app/code/CompanyName/ModuleName/view/adminhtml/templates/helper
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
/** @var $block \Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Gallery\Content */
$elementName = $block->getElement()->getName() . '[images]';
$formName = $block->getFormName();
?>
<div id="<?= $block->getHtmlId() ?>"
class="gallery"
data-mage-init='{"productGallery":{"template":"#<?= $block->getHtmlId() ?>-template"}}'
data-parent-component="<?= $block->escapeHtml($block->getData('config/parentComponent')) ?>"
data-images="<?= $block->escapeHtml($block->getImagesJson()) ?>"
data-types="<?= $block->escapeHtml(
$this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($block->getImageTypes())
) ?>"
>
<?php if (!$block->getElement()->getReadonly()) {?>
<div class="image image-placeholder">
<?= $block->getUploaderHtml() ?>
<div class="product-image-wrapper">
<p class="image-placeholder-text">
<?= /* @escapeNotVerified */ __('Browse to find or drag image here') ?>
</p>
</div>
</div>
<?php } ?>
<?php foreach ($block->getImageTypes() as $typeData) {
?>
<input name="<?= $block->escapeHtml($typeData['name']) ?>"
data-form-part="<?= /* @escapeNotVerified */ $formName ?>"
class="image-<?= $block->escapeHtml($typeData['code']) ?>"
type="hidden"
value="<?= $block->escapeHtml($typeData['value']) ?>"/>
<?php
} ?>
<script id="<?= $block->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="<?= /* @escapeNotVerified */ $elementName ?>[<%- data.file_id %>][position]"
value="<%- data.position %>"
data-form-part="<?= /* @escapeNotVerified */ $formName ?>"
class="position"/>
<input type="hidden"
name="<?= /* @escapeNotVerified */ $elementName ?>[<%- data.file_id %>][file]"
data-form-part="<?= /* @escapeNotVerified */ $formName ?>"
value="<%- data.file %>"/>
<input type="hidden"
name="<?= /* @escapeNotVerified */ $elementName ?>[<%- data.file_id %>][value_id]"
data-form-part="<?= /* @escapeNotVerified */ $formName ?>"
value="<%- data.value_id %>"/>
<input type="hidden"
name="<?= /* @escapeNotVerified */ $elementName ?>[<%- data.file_id %>][label]"
data-form-part="<?= /* @escapeNotVerified */ $formName ?>"
value="<%- data.label %>"/>
<input type="hidden"
name="<?= /* @escapeNotVerified */ $elementName ?>[<%- data.file_id %>][disabled]"
data-form-part="<?= /* @escapeNotVerified */ $formName ?>"
value="<%- data.disabled %>"/>
<input type="hidden"
name="<?= /* @escapeNotVerified */ $elementName ?>[<%- data.file_id %>][displayimage]"
data-form-part="<?= /* @escapeNotVerified */ $formName ?>"
value="<%- data.displayimage %>"/>
<input type="hidden"
name="<?= /* @escapeNotVerified */ $elementName ?>[<%- data.file_id %>][media_type]"
data-form-part="<?= /* @escapeNotVerified */ $formName ?>"
value="image"/>
<input type="hidden"
name="<?= /* @escapeNotVerified */ $elementName ?>[<%- data.file_id %>][removed]"
data-form-part="<?= /* @escapeNotVerified */ $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="<?= /* @escapeNotVerified */ __('Delete image') ?>">
<span>
<?= /* @escapeNotVerified */ __('Delete image') ?>
</span>
</button>
<div class="draggable-handle"></div>
</div>
<div class="image-fade"><span><?= /* @escapeNotVerified */ __('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>
<ul class="item-roles" data-role="roles-labels">
<?php
foreach ($block->getImageTypes() as $typeData) {
?>
<li data-role-code="<?php /* @escapeNotVerified */ echo $block->escapeHtml(
$typeData['code']
) ?>" class="item-role item-role-<?php /* @escapeNotVerified */ echo $block->escapeHtml(
$typeData['code']
) ?>">
<?= /* @escapeNotVerified */ $block->escapeHtml($typeData['label']) ?>
</li>
<?php
}
?>
</ul>
</div>
</script>
<script data-role="img-dialog-container-tmpl" type="text/x-magento-template">
<div class="image-panel" data-role="dialog">
</div>
</script>
<script data-role="img-dialog-tmpl" type="text/x-magento-template">
<div class="image-panel-preview">
<img src="<%- data.url %>" alt="<%- data.label %>" />
</div>
<div class="image-panel-controls">
<strong class="image-name"><%- data.label %></strong>
<fieldset class="admin__fieldset fieldset-image-panel">
<div class="admin__field field-image-description">
<label class="admin__field-label" for="image-description">
<span><?= /* @escapeNotVerified */ __('Alt Text') ?></span>
</label>
<div class="admin__field-control">
<textarea data-role="image-description"
rows="3"
class="admin__control-textarea"
name="<?php /* @escapeNotVerified */
echo $elementName
?>[<%- data.file_id %>][label]"><%- data.label %></textarea>
</div>
</div>
<div class="admin__field field-image-role">
<label class="admin__field-label">
<span><?= /* @escapeNotVerified */ __('Role') ?></span>
</label>
<div class="admin__field-control">
<ul class="multiselect-alt">
<?php
foreach ($block->getMediaAttributes() as $attribute) :
?>
<li class="item">
<label>
<input class="image-type"
data-role="type-selector"
data-form-part="<?= /* @escapeNotVerified */ $formName ?>"
type="checkbox"
value="<?php /* @escapeNotVerified */ echo $block->escapeHtml(
$attribute->getAttributeCode()
) ?>"
/>
<?php /* @escapeNotVerified */ echo $block->escapeHtml(
$attribute->getFrontendLabel()
) ?>
</label>
</li>
<?php
endforeach;
?>
</ul>
</div>
</div>
<div class="admin__field admin__field-inline field-image-size" data-role="size">
<label class="admin__field-label">
<span><?= /* @escapeNotVerified */ __('Image Size') ?></span>
</label>
<div class="admin__field-value" data-message="<?= /* @escapeNotVerified */ __('{size}') ?>"></div>
</div>
<div class="admin__field admin__field-inline field-image-resolution" data-role="resolution">
<label class="admin__field-label">
<span><?= /* @escapeNotVerified */ __('Image Resolution') ?></span>
</label>
<div class="admin__field-value" data-message="<?= /* @escapeNotVerified */ __('{width}^{height} px') ?>"></div>
</div>
<div class="admin__field field-image-hide">
<div class="admin__field-control">
<div class="admin__field admin__field-option">
<input type="checkbox"
id="hide-from-product-page"
data-role="visibility-trigger"
data-form-part="<?= /* @escapeNotVerified */ $formName ?>"
value="1"
class="admin__control-checkbox"
name="<?= /* @escapeNotVerified */ $elementName ?>[<%- data.file_id %>][disabled]"
<% if (data.disabled == 1) { %>checked="checked"<% } %> />
<label for="hide-from-product-page" class="admin__field-label">
<?= /* @escapeNotVerified */ __('Hide from Product Page') ?>
</label>
</div>
</div>
</div>
<div class="admin__field field-display-image">
<div class="admin__field-control">
<div class="admin__field admin__field-option">
<input type="checkbox"
id="display-image-from-product-page-<%- data.file_id %>"
data-role="visibility-trigger-display-image"
data-form-part="<?= /* @escapeNotVerified */ $formName ?>"
value="1"
class="admin__control-checkbox"
name="<?= /* @escapeNotVerified */ $elementName ?>[<%- data.file_id %>][displayimage]"
<% if (data.displayimage == 1) { %>checked="checked"<% } %> />
<label for="display-image-from-product-page-<%- data.file_id %>" class="admin__field-label">
<?= /* @escapeNotVerified */ __('Display Image') ?>
</label>
</div>
</div>
</div>
</fieldset>
</div>
</script>
<?= $block->getChildHtml('new-video') ?>
</div>
<script>
jQuery('body').trigger('contentUpdated');
</script>
=> Create ProductSaveAfter.php observer on this below path for save custom field value in databse :
/app/code/CompanyName/ModuleName/Observer
<?php
namespace CompanyName\ModuleName\Observer;
use Magento\Framework\Event\ObserverInterface;
use \Magento\Store\Model\StoreManagerInterface;
class ProductSaveAfter implements ObserverInterface
{
protected $_objectManager;
protected $messageManager;
protected $_productmetalFactory;
protected $_productdiamondFactory;
protected $_productstoneFactory;
protected $_eavConfig;
protected $stonestore;
protected $scopeConfig;
protected $storeManager;
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Framework\ObjectManagerInterface $objectManager,
\Magento\Framework\App\RequestInterface $request,
\Magento\Eav\Model\Config $eavConfig,
StoreManagerInterface $storeManager,
\Magento\Framework\Message\ManagerInterface $messageManager
) {
$this->_objectManager = $objectManager;
$this->_request = $request;
$this->scopeConfig = $scopeConfig;
$this->_eavConfig = $eavConfig;
$this->storeManager = $storeManager;
$this->messageManager = $messageManager;
}
public function execute(\Magento\Framework\Event\Observer $observer)
{
$data = $this->_request->getParams();
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$array_element = 0;
$images = $data['product']['media_gallery']['images'];
foreach ($images as $value) {
if ($value['value_id'] == "") {
$array_element++;
}
}
$productCollection = $objectManager->create('Magento\Catalog\Model\ResourceModel\Product\CollectionFactory');
$collection = $productCollection->create();
$collection->getSelect()->join(
array('value_entity' => $collection->getTable('catalog_product_entity_media_gallery_value')),
'e.entity_id = value_entity.entity_id',
array('value_id')
);
$collection->getSelect()->join(
array('value_data' => $collection->getTable('catalog_product_entity_media_gallery')),
'value_entity.value_id = value_data.value_id',
array('value')
);
$product = $collection->addFieldToFilter('entity_id', ['eq' => $data['id']]);
$collection_updated = array_slice($product->getData(), "-" . $array_element, $array_element, true);
$new_image_id = [];
foreach ($collection_updated as $key => $value) {
$new_image_id[] = $value['value_id'];
}
try
{
$getDisplayImage = [];
$resource = $objectManager->get('Magento\Framework\App\ResourceConnection');
$connection = $resource->getConnection();
$tableName = $resource->getTableName('catalog_product_entity_media_gallery_value');
foreach ($images as $image) {
if ($image['removed'] != "") {
$sql = "DELETE FROM " . $tableName . " WHERE value_id =" . $image['value_id'];
$connection->query($sql);
}
if ($image['value_id'] == "") {
if (!isset($image['store_id']) || $image['store_id'] == "") {
$store_id = '0';
} else {
$store_id = $image['store_id'];
}
$getDisplayImage[] = $image['displayimage'];
} else {
$sql = "update " . $tableName . " set displayimage = " . $image['displayimage'] . " where value_id = " . $image['value_id'];
$connection->query($sql);
}
}
if ($array_element > 0) {
$count = 0;
foreach ($collection_updated as $key1 => $value1) {
$collection_updated[$key1]['new_displayimage'] = $getDisplayImage[$count];
$count++;
$sql = "update " . $tableName . " set displayimage = " . $collection_updated[$key1]['new_displayimage'] . " where value_id = " . $collection_updated[$key1]['value_id'];
$connection->query($sql);
}
}
} catch (\Magento\Framework\Exception\LocalizedException $e) {
$this->messageManager->addError($e->getMessage());
} catch (\RuntimeException $e) {
$this->messageManager->addError($e->getMessage());
} catch (\Exception $e) {
$this->messageManager->addError($e->getMessage());
}
}
}
=> Create di.xml file on this below path for override module :
/app/code/CompanyName/ModuleName/etc
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Catalog\Model\ResourceModel\Product\Gallery" type="CompanyName\ModuleName\Model\ResourceModel\Product\Gallery" />
</config>
=> Create Gallery.php file on this below path for override module :
/app/code/CompanyName/ModuleName/Model/ResourceModel/Product
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace CompanyName\ModuleName\Model\ResourceModel\Product;
use Magento\Store\Model\Store;
/**
* Catalog product media gallery resource model.
*
* @api
* @since 101.0.0
*/
class Gallery extends \Magento\Catalog\Model\ResourceModel\Product\Gallery {
public function createBatchBaseSelect($storeId, $attributeId) {
$linkField = $this->metadata->getLinkField();
$positionCheckSql = $this->getConnection()->getCheckSql(
'value.position IS NULL',
'default_value.position',
'value.position'
);
$mainTableAlias = $this->getMainTableAlias();
$select = $this->getConnection()->select()->from(
[$mainTableAlias => $this->getMainTable()],
[
'value_id',
'file' => 'value',
'media_type',
]
)->joinInner(
['entity' => $this->getTable(self::GALLERY_VALUE_TO_ENTITY_TABLE)],
$mainTableAlias . '.value_id = entity.value_id',
[$linkField]
)->joinLeft(
['value' => $this->getTable(self::GALLERY_VALUE_TABLE)],
implode(
' AND ',
[
$mainTableAlias . '.value_id = value.value_id',
$this->getConnection()->quoteInto('value.store_id = ?', (int) $storeId),
'value.' . $linkField . ' = entity.' . $linkField,
]
),
['label', 'position', 'disabled', 'displayimage']
)->joinLeft(
['default_value' => $this->getTable(self::GALLERY_VALUE_TABLE)],
implode(
' AND ',
[
$mainTableAlias . '.value_id = default_value.value_id',
$this->getConnection()->quoteInto('default_value.store_id = ?', Store::DEFAULT_STORE_ID),
'default_value.' . $linkField . ' = entity.' . $linkField,
]
),
['label_default' => 'label', 'position_default' => 'position', 'disabled_default' => 'disabled', 'displayimage_default' => 'displayimage']
)->where(
$mainTableAlias . '.attribute_id = ?',
$attributeId
)->where(
$mainTableAlias . '.disabled = 0'
)->order(
$positionCheckSql . ' ' . \Magento\Framework\DB\Select::SQL_ASC
);
return $select;
}
}
=> Now, override product-gallery.js file. So, create requirejs-config.js on this below path for add custom js :
/app/code/CompanyName/ModuleName/view/adminhtml
var config = {
"map": {
"*": {
productGallery: "CompanyName_ModuleName/js/product-gallery",
}
}
}
=> Create product-gallery.js file on this below path :
/app/code/CompanyName/ModuleName/view/adminhtml/web/js
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/**
* @api
*/
define([
'jquery',
'underscore',
'mage/template',
'uiRegistry',
'jquery/ui',
'baseImage',
'productGallery'
], function ($, _, mageTemplate, registry) {
'use strict';
});
Then,
=> Add this line after line no 195 :
'displayimage': imageData.displayimage ? imageData.displayimage : 0,
=> Add this function after line no 515 :
$dialog.on('change', '[data-role=visibility-trigger-displayimage]', $.proxy(function (e) {
var imageData = $dialog.data('imageData');
this.element.trigger('updateVisibility', {
disabled : $("#hide-from-product-page").is(':checked'),
displayimage : $("#virtual-displayimage-from-product-page-"+imageData.file_id).is(':checked'),
imageData: imageData
});
}, this));
=> Add this function after line no 620 :
displayimage = +data.displayimage,
=> Add this function after line no 628 :
$imageContainer.find('[name*="displayimage"]').val(displayimage);
imageData.displayimage = displayimage;