Back to Top

Add Custom Content in Configurable Product Media Gallery – Magento 2

Updated 2 years ago

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.

CustomMediaInConfigurableProductGallery

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.

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


Be the first to comment.

Back to Top

Message Sent!

If you have more details or questions, you can reply to the received confirmation email.

Back to Home