How to change product name dynamically in configurable product when click swatches Magento 2.3

Module Method Working For me in Magento 2.1 / 2.2 /2.3 :: The below Code is to change Name & Description both.


1. app/code/[VendorName]/[ModuleName]/registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    '[VendorName_ModuleName]',
    __DIR__
);

2. app/code/[VendorName]/[ModuleName]/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="[VendorName_ModuleName]" setup_version="1.0.0" />
</config>

3. app/code/[VendorName]/[ModuleName]/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\ConfigurableProduct\Block\Product\View\Type\Configurable">
        <plugin name="[VendorName_ModuleName]-product-block" type="[VendorName]\[ModuleName]\Plugin\Product\View\Type\ConfigurablePlugin" sortOrder="1" />
    </type>
    <type name="Magento\ConfigurableProduct\Model\Product\Type\Configurable">
        <plugin name="[VendorName_ModuleName]-product-model" type="[VendorName]\[ModuleName]\Plugin\Product\Type\ConfigurablePlugin" sortOrder="1" />
    </type>
</config>

4. app/code/[VendorName]/[ModuleName]/Plugin/Product/Type/ConfigurablePlugin.php

<?php 
namespace [VendorName]\[ModuleName]\Plugin\Product\Type;

    class ConfigurablePlugin
    {
        public function afterGetUsedProductCollection(\Magento\ConfigurableProduct\Model\Product\Type\Configurable $subject, $result)
        {
            $result->addAttributeToSelect('name');
            $result->addAttributeToSelect('description');
            return $result;
        }
    }

5. app/code/[VendorName]/[ModuleName]/Plugin/Product/View/Type/ConfigurablePlugin.php

<?php 

namespace [VendorName]\[ModuleName]\Plugin\Product\View\Type;

class ConfigurablePlugin
{
    protected $jsonEncoder;
    protected $jsonDecoder;

    public function __construct(
        \Magento\Framework\Json\DecoderInterface $jsonDecoder,
        \Magento\Framework\Json\EncoderInterface $jsonEncoder
    ){
        $this->jsonEncoder = $jsonEncoder;
        $this->jsonDecoder = $jsonDecoder;
    }

    public function afterGetJsonConfig(\Magento\ConfigurableProduct\Block\Product\View\Type\Configurable $subject, $result)
    {
        $result = $this->jsonDecoder->decode($result);
        $currentProduct = $subject->getProduct();

        if ($currentProduct->getName()) {
            $result['productName'] = $currentProduct->getName();
        }
        if ($currentProduct->getDescription()) {
            $result['productDescription'] = $currentProduct->getDescription();
        }

        foreach ($subject->getAllowProducts() as $product) {
            $result['names'][$product->getId()][] =
                [
                    'name' => $product->getData('name'),
                ];
            $result['descriptions'][$product->getId()][] =
                [
                    'description' => $product->getData('description'),
                ];
        }
        return $this->jsonEncoder->encode($result);
    }
}

6. app/code/[VendorName]/[ModuleName]/view/frontend/requirejs-config.js

var config = {
    map: {
        '*': {
            'Magento_Swatches/js/swatch-renderer':'[VendorName]_[ModuleName]/js/swatch-renderer'
        }
    }
};

7. app/code/[VendorName]/[ModuleName]/view/frontend/web/js/swatch-renderer.js

Copy original JS file(vendor/magento/module-swatches/view/frontend/web/js/swatch-renderer.js & Replace _OnClick function with below code (Line No Approx: 712)

_OnClick: function ($this, $widget, eventName) {
            var $parent = $this.parents('.' + $widget.options.classes.attributeClass),
                $wrapper = $this.parents('.' + $widget.options.classes.attributeOptionsWrapper),
                $label = $parent.find('.' + $widget.options.classes.attributeSelectedOptionLabelClass),
                attributeId = $parent.attr('attribute-id'),
                $input = $parent.find('.' + $widget.options.classes.attributeInput);

            if ($widget.inProductList) {
                $input = $widget.productForm.find(
                    '.' + $widget.options.classes.attributeInput + '[name="super_attribute[' + attributeId + ']"]'
                );
            }

            if ($this.hasClass('disabled')) {
                return;
            }

            if ($this.hasClass('selected')) {
                $parent.removeAttr('option-selected').find('.selected').removeClass('selected');
                $input.val('');
                $label.text('');
                $this.attr('aria-checked', false);
            } else {
                $parent.attr('option-selected', $this.attr('option-id')).find('.selected').removeClass('selected');
                $label.text($this.attr('option-label'));
                $input.val($this.attr('option-id'));
                $input.attr('data-attr-name', this._getAttributeCodeById(attributeId));
                $this.addClass('selected');
                $widget._toggleCheckedAttributes($this, $wrapper);

                /* CUSTOM CODE START */
                if (jQuery('[data-ui-id="page-title-wrapper"]').length && this.options.jsonConfig.names) {
                    if (this.getProduct()) {
                        var iname = this.options.jsonConfig.names[this.getProduct()][0].name
                        if (iname != '') {
                            jQuery('[data-ui-id="page-title-wrapper"]').html(iname);
                        }
                    }
                    else {
                        var productName = this.options.jsonConfig.productName
                        if (productName) {
                            jQuery('[data-ui-id="page-title-wrapper"]').html(productName);
                        }
                    }
                }
                if (jQuery('.description > div.value').length && this.options.jsonConfig.descriptions) {
                    if (this.getProduct()) {
                        var description = this.options.jsonConfig.descriptions[this.getProduct()][0].description
                        if (description) {
                            jQuery('.description > div.value').html(description);
                        }
                    } else {
                        var productDescription = this.options.jsonConfig.productDescription
                        if (productDescription) {
                            jQuery('.description > div.value').html(productDescription);
                        }
                    }
                }
                /* CUSTOM CODE END */

                $widget._Rebuild();

                if ($widget.element.parents($widget.options.selectorProduct)
                    .find(this.options.selectorProductPrice).is(':data(mage-priceBox)')
                ) {
                    $widget._UpdatePrice();
                }

                $widget._loadMedia(eventName);
                $input.trigger('change');
            }
        },

** Output::** enter image description here


You must create a module that will override the "ConfigurableProduct" and "Swatches" modules of Magento.

I made you something based based on a solution from an author of this forum (As soon as I find his name, I will tag him) that will dynamically change the product name, Sku and description. You can make anything you want dynamic with this module. :

First, create your base file in : /app/code/VendorName/ModuleName

In each of the indications below, VendorName and Module/name are to be modified by what you want.

registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'VendorName_ModuleName',
    __DIR__
);

Create directory /app/code/VendorName/ModuleName/etc

Put this file in it : module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="VendorName_ModuleName" setup_version="1.0.0">
        <sequence>
            <module name="Magento_ConfigurableProduct"/>
            <module name="Magento_Swatches"/>
        </sequence>
    </module>
</config>

Now create directory /app/code/VendorName/ModuleName/etc/frontend/

Put this file in it : di.xml

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\ConfigurableProduct\Block\Product\View\Type\Configurable">
        <plugin disabled="false" name="VendorName_ModuleName_Plugin_Magento_ConfigurableProduct_Block_Product_View_Type_Configurable" sortOrder="10" type="VendorName\ModuleName\Plugin\Magento\ConfigurableProduct\Block\Product\View\Type\Configurable"/>
    </type>
    <type name="Magento\Swatches\Block\Product\Renderer\Configurable">
        <plugin disabled="false" name="VendorName_ModuleName_Plugin_Magento_Swatches_Block_Product_Renderer_Configurable" sortOrder="10" type="VendorName\ModuleName\Plugin\Magento\Swatches\Block\Product\Renderer\Configurable"/>
    </type>
</config>

Create directories /app/code/VendorName/ModuleName/Plugin/Magento/ConfigurableProduct/Block/Product/View/Type/ /app/code/VendorName/ModuleName/Plugin/Magento/Swatches/Block/Product/Renderer/

In /app/code/VendorName/ModuleName/Plugin/Magento/ConfigurableProduct/Block/Product/View/Type/

Put this file : Configurable.php

<?php
namespace VendorName\ModuleName\Plugin\Magento\ConfigurableProduct\Block\Product\View\Type;

class Configurable
{
    public function afterGetJsonConfig(\Magento\ConfigurableProduct\Block\Product\View\Type\Configurable $subject, $result) {
        $jsonResult = json_decode($result, true);
        foreach ($subject->getAllowProducts() as $simpleProduct) {
            $id = $simpleProduct->getId();
            foreach($simpleProduct->getAttributes() as $attribute) {
                if(($attribute->getIsVisible() && $attribute->getIsVisibleOnFront()) || in_array($attribute->getAttributeCode(), ['sku','description','name']) ) { // <= Here you can put any attribute you want to see dynamic
                    $code = $attribute->getAttributeCode();
                    $value = (string)$attribute->getFrontend()->getValue($simpleProduct);
                    $jsonResult['dynamic'][$code][$id] = [
                        'value' => $value
                    ];
                }
            }
        }
        $result = json_encode($jsonResult);
        return $result;
    }
}

In /app/code/VendorName/ModuleName/Plugin/Magento/Swatches/Block/Product/Renderer/

<?php

namespace VendorName\ModuleName\Plugin\Magento\Swatches\Block\Product\Renderer;
class Configurable
{
    public function afterGetJsonConfig(\Magento\Swatches\Block\Product\Renderer\Configurable $subject, $result) {
        $jsonResult = json_decode($result, true);
        foreach ($subject->getAllowProducts() as $simpleProduct) {
            $id = $simpleProduct->getId();
            foreach($simpleProduct->getAttributes() as $attribute) {
                if(($attribute->getIsVisible() && $attribute->getIsVisibleOnFront()) || in_array($attribute->getAttributeCode(), ['sku','description','name']) ) { // <= Here you can put any attribute you want to see dynamic
                    $code = $attribute->getAttributeCode();
                    $value = (string)$attribute->getFrontend()->getValue($simpleProduct);
                    $jsonResult['dynamic'][$code][$id] = [
                        'value' => $value
                    ];
                }
            }
        }
        $result = json_encode($jsonResult);
        return $result;
    }
}

Now, we enter in the LAST STEP :

Create Directories : /app/code/VendorName/ModuleName/view/frontend/web/js/model/

In this folder "model", add these files:

attswitch.js

define([
    'jquery',
    'mage/utils/wrapper'
], function ($, wrapper) {
    'use strict';
    return function(targetModule){

        $('h1 span').attr("data-dynamic", "name");

        var reloadPrice = targetModule.prototype._reloadPrice;
        targetModule.prototype.dynamic = {};

        $('[data-dynamic]').each(function(){
            var code = $(this).data('dynamic');
            var value = $(this).html();

            targetModule.prototype.dynamic[code] = value;
        });

        var reloadPriceWrapper = wrapper.wrap(reloadPrice, function(original){
            var dynamic = this.options.spConfig.dynamic;
            console.log(dynamic);
            for (var code in dynamic){
                if (dynamic.hasOwnProperty(code)) {
                    var value = "";
                    var $placeholder = $('[data-dynamic='+code+']');

                    if(!$placeholder.length) {
                        continue;
                    }

                    if(this.simpleProduct){
                        value = this.options.spConfig.dynamic[code][this.simpleProduct].value;
                    } else {
                        value = this.dynamic[code];
                    }

                    $placeholder.html(value);
                }
            }

            return original();
        });

        targetModule.prototype._reloadPrice = reloadPriceWrapper;
        return targetModule;
    };
});

swatch-attswitch.js

/*jshint browser:true jquery:true*/
/*global alert*/
define([
    'jquery',
    'mage/utils/wrapper'
], function ($, wrapper) {
    'use strict';

    return function(targetModule){

        $('h1 span').attr("data-dynamic", "name");

        var updatePrice = targetModule.prototype._UpdatePrice;
        targetModule.prototype.dynamic = {};

        $('[data-dynamic]').each(function(){
            var code = $(this).data('dynamic');
            var value = $(this).html();

            targetModule.prototype.dynamic[code] = value;
        });

        var updatePriceWrapper = wrapper.wrap(updatePrice, function(original){
            var dynamic = this.options.jsonConfig.dynamic;
            console.log(dynamic);
            for (var code in dynamic){
                if (dynamic.hasOwnProperty(code)) {

                    var value = "";
                    var $placeholder = $('[data-dynamic='+code+']');
                    var allSelected = true;

                    if(!$placeholder.length) {
                        continue;
                    }

                    for(var i = 0; i<this.options.jsonConfig.attributes.length;i++){
                        if (!$('div.product-info-main .product-options-wrapper .swatch-attribute.' + this.options.jsonConfig.attributes[i].code).attr('option-selected')){
                            allSelected = false;
                        }
                    }

                    if(allSelected){
                        var products = this._CalcProducts();
                        value = this.options.jsonConfig.dynamic[code][products.slice().shift()].value;
                    } else {
                        value = this.dynamic[code];
                    }

                    $placeholder.html(value);
                }
            }

            return original();
        });

        targetModule.prototype._UpdatePrice = updatePriceWrapper;
        return targetModule;

    };
});

And finally in /app/code/VendorName/ModuleName/view/frontend/

Add this file : requirejs-config.js

var config = {
    config: {
        mixins: {
            'Magento_ConfigurableProduct/js/configurable': {
                'VendorName_ModuleName/js/model/attswitch': true
            },
            'Magento_Swatches/js/swatch-renderer': {
                'VendorName_ModuleName/js/model/swatch-attswitch': true
            }
        }
    }
};

You have now a fully functionnal module that will change dynamically all information you want on product page.

Just pass habitual CLI commands and well done, it work.

Regards,