12

When you change an attribute in a configurable product the product image changes dynamically but the SKU doesn't change.

Also, if you add a configured product to your basket it gives you the image of the configurable product (and not of the simple product) which could be very confusion for customers.

Is there any fix for this issue(s)?

6
  • you have to customize for that its own, its default functionality to show only change image Commented Aug 5, 2016 at 10:12
  • Possible duplicate of Display simple product SKU for configurable products Commented Aug 5, 2016 at 11:31
  • The answer to "why" is "because that's how it's implemented". Magento does not use any attributes of the simple products besides images and the configurable attributes to display the configurable product. In the linked duplicate there's a possible approach to add this feature to Magento 1. I retracted my close vote because I realized you asked for Magento 2.1 - the code will be different but the general approach will be similar. Commented Aug 5, 2016 at 11:33
  • For Magento 1 we have Better Configurable Products, does anybody know if there is such an FOSS extension for Magento 2 ?
    – Alex
    Commented Sep 20, 2017 at 13:43
  • test on 2.2.3, not work, i don't understand what happened maybe it's the problem of my theme Commented Mar 27, 2018 at 20:27

7 Answers 7

16

I did that once for Magento 2.0, don't have the code available but can show you where you need to make changes:

  • Write a Plugin for Magento\ConfigurableProduct\Block\Product\View\Type\Configurable::getJsonConfig() and add the SKUs to the result:

    $config['skus'] = [];
    foreach ($subject->getAllowProducts() as $simpleProduct) {
        $config['skus'][$simpleProduct->getId()] = $simpleProduct->getSku();
    }
    
  • Extend Product.Config from app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/configurable.js using RequireJS. A good place to add the code to change the displayed SKU is reloadPrice(). You will have access to the SKUs via this.config.skus
3
  • I am surprised these is not an event dispatched in the getJsonConfig function..
    – tread
    Commented Jan 18, 2017 at 13:53
  • @StevieG I think in Magento 1 there was an event, but in Magento 2 plugins are preferred over events, so events that can be replaced with a plugin are removed gradually. Commented Jan 18, 2017 at 14:27
  • Oh no, I used an observer for this same function with bundled products catalog_product_option_price_configuration_after...I fear it may be removed
    – tread
    Commented Jan 18, 2017 at 15:13
33

I wrote the module based on Fabian Schmengler's solution. This works for me on Magento 2.1.3.

/app/code/YourVendor/YourModule/view/frontend/requirejs-config.js

var config = {
    config: {
        mixins: {
            'Magento_ConfigurableProduct/js/configurable': {
                'YourVendor_YourModule/js/model/skuswitch': true
            }
        }
    }
};

/app/code/YourVendor/YourModule/view/frontend/web/js/model/skuswitch.js

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

    return function(targetModule){

        var reloadPrice = targetModule.prototype._reloadPrice;
        var reloadPriceWrapper = wrapper.wrap(reloadPrice, function(original){
            //do extra stuff

            //call original method
            var result = original();

            //do extra stuff
            var simpleSku = this.options.spConfig.skus[this.simpleProduct];

            if(simpleSku != '') {
                $('div.product-info-main .sku .value').html(simpleSku);
            }


            //return original value
            return result;
        });

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

/app/code/YourVendor/YourModule/Plugin/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php

namespace YourVendor\YourModule\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);

        $jsonResult['skus'] = [];
        foreach ($subject->getAllowProducts() as $simpleProduct) {
            $jsonResult['skus'][$simpleProduct->getId()] = $simpleProduct->getSku();
        }


        $result = json_encode($jsonResult);

        return $result;
    }
}

/app/code/YourVendor/YourModule/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 disabled="false" name="YourVendor_YourModule_Plugin_Magento_ConfigurableProduct_Block_Product_View_Type_Configurable" sortOrder="10" type="YourVendor\YourModule\Plugin\Magento\ConfigurableProduct\Block\Product\View\Type\Configurable"/>
    </type>
</config>

Feedback is appreciated! I got this by trial&error based on http://alanstorm.com/the-curious-case-of-magento-2-mixins/

5
  • 1
    thanks a lot. Saved me a bit of time. But I had to change the name and location on require-config.js to /app/code/YourVendor/YourModule/view/frontend/requirejs-config.js
    – TNordkvist
    Commented Jan 31, 2017 at 9:26
  • @TNordkvist You are right, my mistake! Fixed in the answer.
    – nbjohan
    Commented Jan 31, 2017 at 14:42
  • 5
    A small addition and now it works on swatches as well github.com/netrixab/magento2-configurable-sku-switch
    – TNordkvist
    Commented Feb 2, 2017 at 8:35
  • Works on 2.1.9, I'm to magento and this has saved me lots of time
    – gabehou
    Commented Sep 19, 2017 at 20:49
  • If parent product doesn't have description then how to display our simple product description based on selection ? Commented Dec 26, 2019 at 18:52
1

Works great on Magento 2.2.1. For those who are new to Magento Module Development, you have to create few more files before follow @nbjohan's tutorial.

Create app/code/[vendor-name]/[module-name]/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="[Vendor]_[Module]" setup_version="1.0.0">
</module>

app/code/[vendor-name]/[module-name]/registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'[Vendor]_[Module]',
__DIR__
);

Upgrade on server using: php bin/magento setup:upgrade

0

Following code work for me you can try it.

app\code\Vendor\Extension\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 disabled="false" name="Vendor_Extension_Plugin_ConfigurableProduct_Block_Product_View_Type_Configurable" sortOrder="10" type="Vendor\Extension\Plugin\ConfigurableProduct\Block\Product\View\Type\Configurable"/>
    </type>
 
    <type name="Magento\Swatches\Block\Product\Renderer\Configurable">
        <plugin disabled="false" name="Vendor_Extension_ConfigurableSkuSwitch_Plugin_Magento_Swatches_Block_Product_Renderer_Configurable" sortOrder="10" type=" Vendor \ Extension \Plugin\Swatches\Block\Product\Renderer\Configurable"/>
    </type>
</config>

app\code\Vendor\Extension\Plugin\ConfigurableProduct\Block\Product\View\Type\Configurable.php

<?php
namespace Vendor\Extension\Plugin\ConfigurableProduct\Block\Product\View\Type;
 
class Configurable
{
 
    public function afterGetJsonConfig(
        \Magento\ConfigurableProduct\Block\Product\View\Type\Configurable $subject,
        $result
    ) {
 
    $jsonResult = json_decode($result, true);
    $jsonResult['skus'] = [];
        foreach ($subject->getAllowProducts() as $simpleProduct) {
            $jsonResult['skus'][$simpleProduct->getId()] = $simpleProduct->getSku();
    }
    $result = json_encode($jsonResult);
        return $result;
    }
}

app\code\Vendor\Extension\Plugin\Swatches\Block\Product\Renderer\Configurable.php

<?php
namespace Vendor\Extension\Plugin\Swatches\Block\Product\Renderer;
 
class Configurable
{
    public function afterGetJsonConfig(\Magento\Swatches\Block\Product\Renderer\Configurable $subject, $result) {
 
        $jsonResult = json_decode($result, true);
        $jsonResult['skus'] = [];
 
        foreach ($subject->getAllowProducts() as $simpleProduct) {
           $jsonResult['skus'][$simpleProduct->getId()] = $simpleProduct->getSku();
        }
        $result = json_encode($jsonResult);
        return $result;
    }
}

app\code\Vendor\Extension\view\frontend\requirejs-config.js

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

app\code\Vendor\Extension\view\frontend\web\js\model\skuswitch.js

    define([
    'jquery',
    'mage/utils/wrapper'
], function ($, wrapper) {
    'use strict';
 
    return function(targetModule){
 
        var reloadPrice = targetModule.prototype._reloadPrice;
        var reloadPriceWrapper = wrapper.wrap(reloadPrice, function(original){
        var result = original();
        var simpleSku = this.options.spConfig.skus[this.simpleProduct];
 
            if(simpleSku != '') {
                $('div.product-info-main .sku .value').html(simpleSku);
            }
            return result;
        });
        targetModule.prototype._reloadPrice = reloadPriceWrapper;
        return targetModule;
    };
});

app\code\Vendor\Extension\view\frontend\web\js\model\swatch-skuswitch.js

define([
    'jquery',
    'mage/utils/wrapper'
], function ($, wrapper) {
    'use strict';
 
    return function(targetModule){
        var updatePrice = targetModule.prototype._UpdatePrice;
        targetModule.prototype.configurableSku = $('div.product-info-main .sku .value').html();
        var updatePriceWrapper = wrapper.wrap(updatePrice, function(original){
            var allSelected = true;
            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;
                }
            }
            var simpleSku = this.configurableSku;
            if (allSelected){
                var products = this._CalcProducts();
                simpleSku = this.options.jsonConfig.skus[products.slice().shift()];
            }
            $('div.product-info-main .sku .value').html(simpleSku);
              return original();
        });
 
        targetModule.prototype._UpdatePrice = updatePriceWrapper;
        return targetModule;
    };
});
0

Out of the box, when choosing options, the images and the price will change. But not SKU.

More information about which elements on the page change when options are selected can be found here: Magento\ConfigurableProduct\Block\Product\View\Type\Configurable::getJsonConfig().

In order to display the SKU of the selected product, you can create a Plugin (Interceptor) for Magento\ConfigurableProduct\Block\Product\View\Type\Configurable::getJsonConfig() where you need to add missing SKU for each simple product.

Switching SKU when selecting an option can be implemented in vendor/magento/module-swatches/view/base/web/js/swatch-renderer.js and vendor/magento/module-configurable-product/view/frontend/web/js/configurable.js depending on the type of attribute.


I made free VCT Change SKU Dynamically module that solve this problem.

-1

This does not appear to be working for me on Version 2.2.2. Can anyone assist me? Been trying for days.

app/code/D4tools/AttributeSkuChanger/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 disabled="false" name="D4tools_AttributeSkuChanger_Plugin_Magento_ConfigurableProduct_Block_Product_View_Type_Configurable" sortOrder="10" type="D4tools\AttributeSkuChanger\Plugin\Magento\ConfigurableProduct\Block\Product\View\Type\Configurable"/>
    </type>
</config>

app/code/D4tools/AttributeSkuChanger/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="D4tools_AttributeSkuChanger" setup_version="1.0.0"></module>.
</config>

app/code/D4tools/AttributeSkuChanger/Plugin/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php

<?php
namespace D4tools\AttributeSkuChanger\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);

        $jsonResult['skus'] = [];
        foreach ($subject->getAllowProducts() as $simpleProduct) {
            $jsonResult['skus'][$simpleProduct->getId()] = $simpleProduct->getSku();
        }


        $result = json_encode($jsonResult);

        return $result;
    }
}

app/code/D4tools/AttributeSkuChanger/view/frontend/web/js/model/skuswitch.js

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

    return function(targetModule){

        var reloadPrice = targetModule.prototype._reloadPrice;
        var reloadPriceWrapper = wrapper.wrap(reloadPrice, function(original){
            //do extra stuff

            //call original method
            var result = original();

            //do extra stuff
            var simpleSku = this.options.spConfig.skus[this.simpleProduct];

            if(simpleSku != '') {
                $('div.product-info-main .sku .value').html(simpleSku);
            }


            //return original value
            return result;          
        });

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

app/code/D4tools/AttributeSkuChanger/view/frontend/requirejs-config.js

    var config = {
    config: {
        mixins: {
            'Magento_ConfigurableProduct/js/configurable': {
                'D4tools_AttributeSkuChanger/js/model/skuswitch': true
            }
        }
    }
};
-3

How to get this one to work in Magento 2.2.6 foldernames and placement.

I downloaded this one: This works for me on Magento 2.2.5, https://github.com/andreecz/magento2-configurable-dynamic

And placed it like this app/code/Andering/ConfigurableDynamic

And added

    <referenceBlock name="product.info.sku">
        <arguments>
            <argument name="add_attribute" xsi:type="string">itemprop="sku" data-dynamic="sku"</argument>
        </arguments>
    </referenceBlock>

to my theme in catalog_product_view.phtml

2
  • I am having issues on 2.2.6 as well, it works on 2.2.5 though. Did you figure this out?
    – Goose84
    Commented Jan 14, 2019 at 12:23
  • Without a working link, the answer is of little use.
    – Victor S.
    Commented Nov 26, 2021 at 15:10

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