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::**
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,