When you create a configurable product in Magento 2 and assign simple products to it using a selected attribute, those simple products can be selected from a dropdown on the product detail page. The images and price change, but the SKU does not. The dropdown also displays only the labels of the underlying attribute rather than the name of the associated simple product. Instead, the price difference compared to the currently selected simple product is displayed.
We wanted to achieve two things: hide the price difference and, instead, display the name of the respective associated simple product next to the attribute label. First, we created a small plugin and added the following lines to
\app\code\Vendorname\Modulename\etc\di.xml
to enable the plugin:
<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>
The desired plugin class in the file
\app\code\Vendorname\Modulename\Plugin\Magento\ConfigurableProduct\Block\Product\View\Type\Configurable.php
then looks like this:
<?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);
$jsonResult['skus'] = [];
$jsonResult['simple_product_names'] = [];
foreach ($subject->getAllowProducts() as $simpleProduct) {
$jsonResult['skus'][$simpleProduct->getId()] = $simpleProduct->getSku();
$jsonResult['simple_product_names'][$simpleProduct->getId()] = $simpleProduct->getName();
}
$result = json_encode($jsonResult);
return $result;
}
}
In other words, we retrieve the SKUs and names of the underlying simple products. We now need to make these available in the select box (the product names). We do this in the file
\app\design\frontend\Packagename\Templatename\Magento_ConfigurableProduct\web\js\configurable.js
After the following lines:
if (typeof allowedProducts[0] !== 'undefined' &&
typeof optionPrices[allowedProducts[0]] !== 'undefined') {
allowedProductMinPrice = this._getAllowedProductWithMinPrice(allowedProducts);
optionFinalPrice = parseFloat(optionPrices[allowedProductMinPrice].finalPrice.amount);
optionPriceDiff = optionFinalPrice - basePrice;
add the following lines to prevent the price differences from being displayed and replace them with the product names:
options[i].label = options[i].label + ': ' + this.options.spConfig.simple_product_names[options[i].products[0]];options[i].label = options[i].label + ': ' + this.options.spConfig.simple_product_names[options[i].products[0]];
if (optionPriceDiff !== 0 && 1==2) {
Always make sure that the assets are redeployed after making changes. In this case, the following file
\pub\static\frontend\Packagename\Templatename\de_DE\Magento_ConfigurableProduct\js\configurable.js
must be deleted (de_DE should of course be adjusted if necessary for a different language in the store view). Copy the complete original configurable.js file from the core before making the modifications.
Now only the SKU change is missing:
For this, create the file
\app\code\Vendorname\Modulename\view\frontend\requirejs-config.js
with the following content:
var config = {
config: {
mixins: {
'Magento_ConfigurableProduct/js/configurable': {
'Vendorname_Modulename/js/model/skuswitch': true
}
}
}
};
Then create the referenced file
\app\code\Vendorname\Modulename\view\frontend\web\js\model\skuswitch.js
with the following content:
/*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;
};
});
That's it. Tested at our web agency in a Magento 2 online store running Magento CE 2.3.1.
