Add Custom Content in Configurable Product Media Gallery – Magento 2
Hello Friends, in this blog, we will learn how can we add custom content or media to Configurable Products’ Fotorama media gallery at the front end.
Here, I have added some extra content to the media gallery in the first position. You can change the content position as per your requirements.
If you are a vendor and want to attract more customers to your e-commerce store. Explore our WebAR Magento 2 extension.
As we have to add content in the configurable products’ media gallery when we deep-dive into the code, we will find that configurable product images are being changed/loaded from the <magento-root-dir.>/vendor/magento/module-configurable-product/view/frontend/web/js/configurable.js file.
Where, the _changeProductImage() function is responsible for achieving this.
So, to add the custom content I have overridden the _changeProductImage() function and added some required files which are required to achieve our goal.
First of all, we will create a demo module. Here, I have created the Webkul_ExtraContentInFotorama module. Further, follow the below steps:
1. Create catalog_product_view_type_configurable.xml file inside the <magento-root-dir>/app/code/Webkul/ExtraContentInFotorama/view/frontend/layout/ directory.
<?xml version="1.0"?>
<!--
/**
* Webkul Software.
*
* @category Webkul
* @package Webkul_ExtraContentInFotorama
* @author Webkul Software Private Limited
* @copyright Webkul Software Private Limited (https://webkul.com)
* @license https://store.webkul.com/license.html
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="product.info.options.wrapper">
<referenceBlock class="Webkul\ExtraContentInFotorama\Block\Product\Renderer\Configurable"
name="product.info.options.swatches">
</referenceBlock>
</referenceBlock>
</body>
</page>
2. Create a Configurable.php file inside the <magento-root-dir.>/app/code/Webkul/ExtraContentInFotorama/Block/Product/Renderer/ directory.
<?php
/**
* Webkul Software.
*
* @category Webkul
* @package Webkul_ExtraContentInFotorama
* @author Webkul Software Private Limited
* @copyright Webkul Software Private Limited (https://webkul.com)
* @license https://store.webkul.com/license.html
*/
declare(strict_types = 1);
namespace Webkul\ExtraContentInFotorama\Block\Product\Renderer;
/**
* Swatch renderer block
*/
class Configurable extends \Magento\Swatches\Block\Product\Renderer\Configurable
{
/**
* Path to default template file with standard Configurable renderer.
*/
public const CONFIGURABLE_RENDERER_TEMPLATE = 'Webkul_ExtraContentInFotorama::product/view/type/options/configurable.phtml';
/**
* Return renderer template
*
* Template for product with swatches is different from product without swatches
*
* @return string
*/
protected function getRendererTemplate()
{
return $this->isProductHasSwatchAttribute() ?
parent::SWATCH_RENDERER_TEMPLATE : self::CONFIGURABLE_RENDERER_TEMPLATE;
}
}
3. Create a configurable.phtml file inside the <magento-root-dir>/app/code/Webkul/ExtraContentInFotorama/view/frontend/templates/product/view/type/options/ directory.
<?php
/**
* Webkul Software.
*
* @category Webkul
* @package Webkul_ExtraContentInFotorama
* @author Webkul Software Private Limited
* @copyright Webkul Software Private Limited (https://webkul.com)
* @license https://store.webkul.com/license.html
*/
?>
<?php
/** @var $block \Magento\ConfigurableProduct\Block\Product\View\Type\Configurable*/
$product = $block->getProduct();
$_attributes = $block->decorateArray($block->getAllowAttributes());
$linkUrl = "https://webkul.com/blog/design-patterns-in-magento-2/";
$thumbnailImage = "Provide a thumbnail Image URL";
$linkContent = "Design Patterns in Magento 2";
?>
<?php if ($product->isSaleable() && count($_attributes)) :?>
<?php foreach ($_attributes as $_attribute) : ?>
<div class="field configurable required">
<label class="label" for="attribute<?= $block->escapeHtmlAttr($_attribute->getAttributeId()) ?>">
<span><?= $block->escapeHtml($_attribute->getProductAttribute()->getStoreLabel()) ?></span>
</label>
<div class="control">
<select name="super_attribute[<?= $block->escapeHtmlAttr($_attribute->getAttributeId()) ?>]"
data-selector="super_attribute[<?= $block->escapeHtmlAttr($_attribute->getAttributeId()) ?>]"
data-validate="{required:true}"
id="attribute<?= $block->escapeHtmlAttr($_attribute->getAttributeId()) ?>"
class="super-attribute-select">
<option value=""><?= $block->escapeHtml(__('Choose an Option...')) ?></option>
</select>
</div>
</div>
<?php endforeach; ?>
<script type="text/x-magento-init">
{
"#product_addtocart_form": {
"configurable": {
"spConfig": <?= /* @noEscape */ $block->getJsonConfig() ?>,
"gallerySwitchStrategy": "<?= $block->escapeJs($block->getVar(
'gallery_switch_strategy',
'Magento_ConfigurableProduct'
) ?: 'replace'); ?>",
"thumbnailImage":"<?= /* @noEscape */$thumbnailImage?>",
"linkUrl":"<?= /* @noEscape */ $linkUrl?>",
"linkContent":"<?= /* @noEscape */ $linkContent?>"
}
},
"*" : {
"Magento_ConfigurableProduct/js/catalog-add-to-cart": {}
}
}
</script>
<?php endif;?>
4. Create a requires-config.js file to mention the mixin file for the configurable.js file inside the <magento-root-dir.>/app/code/Webkul/ExtraContentInFotorama/view/frontend/ directory.
/**
* Webkul Software.
*
* @category Webkul
* @package Webkul_ExtraContentInFotorama
* @author Webkul Software Private Limited
* @copyright Webkul Software Private Limited (https://webkul.com)
* @license https://store.webkul.com/license.html
*/
var config = {
config: {
mixins: {
'Magento_ConfigurableProduct/js/configurable' : {'Webkul_ExtraContentInFotorama/js/configurable':true}
}
}
};
5. Create a configurable.js file inside the <magento-root-dir.>/app/code/Webkul/ExtraContentInFotorama/view/frontend/web/js/ directory.
/**
* Webkul Software.
*
* @category Webkul
* @package Webkul_ExtraContentInFotorama
* @author Webkul Software Private Limited
* @copyright Webkul Software Private Limited (https://webkul.com)
* @license https://store.webkul.com/license.html
*/
define([
'jquery',
'underscore',
'mage/translate'
], function ($, _, $t) {
'use strict';
return function (configurable) {
$.widget('mage.configurable', configurable, {
/**
* Change displayed product image according to chosen options of configurable product
*
* @private
*/
_changeProductImage: function () {
var self = this;
//Thumbnail Image for Custom Content////
var contentThumbnailImage = self.options.thumbnailImage;
var images,
initialImages = this.options.mediaGalleryInitial,
gallery = $(this.options.mediaGallerySelector).data('gallery');
/////////Load Custom Content in Fotorama/////
self._loadCustomContent();
//////////////////////////////
if (_.isUndefined(gallery)) {
$(this.options.mediaGallerySelector).on('gallery:loaded', function () {
this._changeProductImage();
}.bind(this));
return;
}
images = this.options.spConfig.images[this.simpleProduct];
if (images) {
//Remove Extra Content from Fotorama////
initialImages = self._removeExtraContentfromArray(initialImages);
images = self._removeExtraContentfromArray(images);
//Push Extra Content in Fotorama////
self._pushContent(images, contentThumbnailImage);
//////////////////
images = this._sortImages(images);
if (this.options.gallerySwitchStrategy === 'prepend') {
images = images.concat(initialImages);
}
images = $.extend(true, [], images);
images = this._setImageIndex(images);
gallery.updateData(images);
this._addFotoramaVideoEvents(false);
} else {
//Remove Extra Content from Fotorama////
initialImages = self._removeExtraContentfromArray(initialImages);
//Push Extra Content in Fotorama////
self._pushContent(initialImages, contentThumbnailImage);
gallery.updateData(initialImages);
this._addFotoramaVideoEvents(true);
}
},
/**
* Set correct indexes for image set.
*
* @param {Array} images
* @private
*/
_setImageIndex: function (images) {
var length = images.length,
i, j = 1;
for (i = 0; length > i; i++) {
if (images[i].type == "ExtraContent") {
images[i].i = 1;
} else {
images[i].i = j + 1;
}
}
return images;
},
/**
* Delete Additional content from array
*
* @param {Array} fotoramaContentArray
* @returns {Array}
* @private
*/
_removeExtraContentfromArray: function(fotoramaContentArray) {
fotoramaContentArray = fotoramaContentArray.filter(
element => element.type !== "ExtraContent"
);
return fotoramaContentArray;
},
/**
* Push content in array
*
* @param {Array} fotoramaContentArray
* @param {string} contentThumbnailImage
* @private
*/
_pushContent: function(fotoramaContentArray, contentThumbnailImage) {
var self = this;
if (typeof fotoramaContentArray != "undefined" &&
(self.options.linkUrl != "" || self.options.linkUrl != null)) {
fotoramaContentArray.unshift({
thumb: contentThumbnailImage,
src: self.options.linkUrl,
type: 'ExtraContent',
caption: self.options.linkContent,
isMain: "true",
position: 0
});
}
},
/**
* Load custom content
*
* @private
*/
_loadCustomContent: function() {
var self = this;
var galleryDivFotorama = $('div.gallery-placeholder > div.fotorama');
var variantText = "None";
var variantTextColor = "#FFED8F";
//Get Selected Variant Value
variantText = self._getSelectedVariant();
switch (variantText) {
case "Mango Velvet": variantTextColor = "#FF8200"; break;
case "Peacock Velvet": variantTextColor = "#A7D46F"; break;
}
galleryDivFotorama.on('fotorama:load', function fotorama_onLoad(e, fotorama, extra) {
if (extra.frame.type === 'ExtraContent' && extra.frame.src != "") {
var extraContentHtml = '';
extraContentHtml += '<div id="wkExtraContent" ';
extraContentHtml += 'style="background-color:'+variantTextColor+';">';
extraContentHtml += '<h1 style="margin-top:250px">'+'Extra Content'+'</h1>';
///Show Variant Text///
if (variantText != '') {
extraContentHtml += '<p style="font-size:20px">Selected Variant:</p>';
extraContentHtml += '<p style="font-size:18px">'+variantText+'</p><br/>';
}
/////////////////
extraContentHtml += '<a href="'+self.options.linkUrl+'" style="font-size:18px">'
extraContentHtml += self.options.linkContent+'</a>';
extraContentHtml += '</div>';
extra.frame.$stageFrame.html(extraContentHtml);
}
});
},
/**
* Get Selected Variant Value
*
* @return {string}
* @private
*/
_getSelectedVariant: function() {
var variantTextVal = "";
var variantTextArr = [];
var selectedText = $('.product-options-wrapper select[id^="attribute"] option:selected').text();
if (selectedText.indexOf('+') == -1) {
variantTextVal = selectedText;
} else {
variantTextArr = selectedText.split('+');
variantTextVal = $.trim(variantTextArr[0]);
}
return variantTextVal;
},
});
return $.mage.configurable;
};
});
6. After adding the above code to your module. Deploy the code and see the result.
Refer to the below image for the result.
Hope this will be helpful. Thanks 🙂
You may also check the Magento 2 Advanced Media Manager extension to edit the images present in the media gallery and add watermarks, filter, rotate, resize, and more.
You can check our next blog Magento 2 Custom Content in Configurable Product Media Gallery to display custom content in the media gallery in text and visual swatch case on the configurable product page.