2

How I can change my configurable product name and description dynamically when one option is selected, right now is change only the image, I need to do the same with the name and description.

HTML structure:

<div class="product media">
    <div class="product attribute description">
        <div class="value">
            <p>text description.</p>
        </div>
    </div>
</div>

enter image description here

3

You can try below custom module and modify according to your requirement.

app/code/Anshu/SCdata/registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Anshu_SCdata',
    __DIR__
);

app/code/Anshu/SCdata/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="Anshu_SCdata" setup_version="1.0.0">
            <sequence>
                <module name="Magento_Swatches"/>
            </sequence>
        </module>
    </config>

app/code/Anshu/SCdata/etc/frontend/di.xml

<?xml version="1.0" encoding="UTF-8"?>
    <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="anshu_configurable_product_configurable"
                    type="Anshu\SCdata\Block\ConfigurableProduct\Product\View\Type\Configurable"
                    sortOrder="1"/>
        </type>
    </config>

app/code/Anshu/SCdata/Block/ConfigurableProduct/Product/View/Type/Configurable.php

<?php

namespace Anshu\SCdata\Block\ConfigurableProduct\Product\View\Type;

use Magento\Framework\Json\EncoderInterface;
use Magento\Framework\Json\DecoderInterface;

class Configurable
{
    protected $jsonEncoder;
    protected $jsonDecoder;
    protected $_productRepository;

    public function __construct(
            \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
            EncoderInterface $jsonEncoder,
            DecoderInterface $jsonDecoder
    ) {
        $this->jsonDecoder = $jsonDecoder;
        $this->jsonEncoder = $jsonEncoder;
        $this->_productRepository = $productRepository;
    }

    public function getProductById($id)
    {
        return $this->_productRepository->getById($id);
    }

    public function aroundGetJsonConfig(
        \Magento\ConfigurableProduct\Block\Product\View\Type\Configurable $subject,
        \Closure $proceed
    )
    {
        $sname = [];
        $sdescription = [];

        $config = $proceed();
        $config = $this->jsonDecoder->decode($config);

        foreach ($subject->getAllowProducts() as $prod) {
            $id = $prod->getId();
            $product = $this->getProductById($id);
            $sname[$id] = $product->getName();
            $sdescription[$id] = $product->getDescription();
        }
        $config['sname'] = $sname;
        $config['sdescription'] = $sdescription;

        return $this->jsonEncoder->encode($config);
    }
}

app/code/Anshu/SCdata/view/frontend/requirejs-config.js

var config = {
    map: {
        '*': {
            'Magento_Swatches/js/swatch-renderer' : 'Anshu_SCdata/js/swatch-renderer',
            'magento-swatch.renderer' : 'Magento_Swatches/js/swatch-renderer',
        }
    }
};

app/code/Anshu/SCdata/view/frontend/web/js/swatch-renderer.js

define([
  'jquery',
  'jquery/ui',
  'magento-swatch.renderer'
], function($){

  $.widget('anshu.SwatchRenderer', $.mage.SwatchRenderer, { 

        /**
         * Event for swatch options
         *
         * @param {Object} $this
         * @param {Object} $widget
         * @private
         */
        _OnClick: function ($this, $widget) {
            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);
            }

            $widget._Rebuild();

            // Custom Code starts
            var iname = $widget.options.jsonConfig.sname[this.getProduct()];
            var idescription = $widget.options.jsonConfig.sdescription[this.getProduct()];

            if(idescription != ''){
                $('[data-role="content"]').find('.description .value').html(idescription);
            }
            if(iname != ''){
                $('[data-ui-id="page-title-wrapper"]').html(iname);
            }
            // Custom code ends

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

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

    });

  return $.anshu.SwatchRenderer;
});
  • Hi thanks for your complete answer, I have only one issue the description is not work, I really don't know what is happened. can you check please? – Robert Jan 27 '18 at 14:26
  • I forgot to tell you, in my custom theme I move the description here: <move element="product.info.description" destination="product.info.media" before="product.info.media.image"/> maybe this can be the issue? – Robert Jan 27 '18 at 14:33
  • Change the code $('[data-role="content"]').find('.description .value').html(idescription); according to your placement of the element. Rest of the code will be the same. – Anshu Mishra Jan 29 '18 at 4:56
  • I already do this but still not working – Robert Jan 29 '18 at 7:28
  • you have any idea what is wrong with this module? why is not work description? – Robert Jan 30 '18 at 11:10
2

Try following module:

  1. app/code/[VendorName]/[ModuleName]/registration.php
  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">
        <sequence>
            <module name="Magento_Swatches"/>
        </sequence>
    </module>
</config>
  1. 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>
  1. 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('description');
        return $result;
    }
}
  1. 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->getDescription()) {
            $result['productDescription'] = $currentProduct->getDescription();
        }

        foreach ($subject->getAllowProducts() as $product) {
            $result['descriptions'][$product->getId()][] =
                [
                    'description' => $product->getData('description'),
                ];
        }

        return $this->jsonEncoder->encode($result);
    }
}
  1. app/code/[VendorName]/[ModuleName]/view/frontend/requirejs-config.js
var config = {
    map: {
        '*': {
            'Magento_Swatches/js/swatch-renderer':'[VendorName]_[ModuleName]/js/swatch-renderer'
        }
    }
};
  1. app/code/[VendorName]/[ModuleName]/view/frontend/web/js/swatch-renderer.js
_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('.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');
},

Note: Copy original JS file(vendor/magento/module-swatches/view/frontend/web/js/swatch-renderer.js) and paste on the above path and update above function(_OnClick) OR you can customize JS code as per your requirement. Here, you can also use minix to override JS function.

  • Hi thank you, but I think your code is not complete, I have errors – Robert Jan 27 '18 at 13:42
  • how to change the custom attribute for this – Divya May 28 at 9:43
-1

You can use an observer and event product before save and set your dynamically created description based in certain conditions

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.