├── Block └── Product │ └── View │ └── Attributes.php ├── Helper └── ConfigurableDynamicHelper.php ├── Plugin └── Magento │ └── ConfigurableProduct │ └── Block │ └── Product │ └── View │ └── Type │ └── Configurable.php ├── README.md ├── composer.json ├── etc ├── frontend │ └── di.xml └── module.xml ├── registration.php └── view └── frontend ├── layout └── catalog_product_view.xml ├── requirejs-config.js ├── templates └── block_wrap.phtml └── web └── js └── model ├── skuswitch.js └── swatch-skuswitch.js /Block/Product/View/Attributes.php: -------------------------------------------------------------------------------- 1 | _product = $product; 12 | } 13 | 14 | public function getCacheKeyInfo() 15 | { 16 | $info = parent::getCacheKeyInfo(); 17 | $info['product_id'] = $this->getProduct()->getId(); 18 | return $info; 19 | } 20 | 21 | 22 | } -------------------------------------------------------------------------------- /Helper/ConfigurableDynamicHelper.php: -------------------------------------------------------------------------------- 1 | layout = $layout; 22 | $this->serializer = $serializer; 23 | } 24 | 25 | public function serialize($data): string 26 | { 27 | return $this->serializer->serialize($data); 28 | } 29 | 30 | public function unserialize(string $string) 31 | { 32 | return $this->serializer->unserialize($string); 33 | } 34 | 35 | public function addBlock( 36 | string $dynamicDataId, 37 | string $blockId, 38 | string $blockClass, 39 | array $config, 40 | Product $simpleProduct 41 | ): array { 42 | $config['dynamic'][$dynamicDataId][$simpleProduct->getId()] = [ 43 | 'value' => $this->getBlockHtml($blockId, $blockClass, $simpleProduct), 44 | ]; 45 | 46 | return $config; 47 | } 48 | 49 | private function getBlockHtml(string $blockId, string $blockClass, Product $simpleProduct): string 50 | { 51 | /** @var AbstractProduct $originalBlock */ 52 | $originalBlock = $this->layout->getBlock($blockId); 53 | 54 | if(!$originalBlock) { 55 | return ''; 56 | } 57 | 58 | $block = $this->layout->createBlock($blockClass, '', ['data' => $originalBlock->getData()]); 59 | $block->setTemplate($originalBlock->getTemplate()) 60 | ->setProduct($simpleProduct); 61 | 62 | return $block->toHtml(); 63 | } 64 | } -------------------------------------------------------------------------------- /Plugin/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php: -------------------------------------------------------------------------------- 1 | dynamicHelper = $dynamicHelper; 23 | } 24 | 25 | public function afterGetJsonConfig(\Magento\ConfigurableProduct\Block\Product\View\Type\Configurable $subject, $result) { 26 | 27 | $jsonResult = $this->dynamicHelper->unserialize($result); 28 | 29 | foreach ($subject->getAllowProducts() as $simpleProduct) { 30 | $jsonResult = $this->addVisibleAttributes($simpleProduct, $jsonResult); 31 | $jsonResult = $this->dynamicHelper->addBlock( 32 | 'product_attributes', 33 | 'product.attributes', 34 | Attributes::class, 35 | $jsonResult, 36 | $simpleProduct 37 | ); 38 | $jsonResult = $this->addProductName($jsonResult, $simpleProduct); 39 | } 40 | 41 | $result = $this->dynamicHelper->serialize($jsonResult); 42 | return $result; 43 | } 44 | 45 | private function addProductName(array $config, Product $product): array 46 | { 47 | $config['dynamic']['product_name'][$product->getId()] = [ 48 | 'value' => $product->getName(), 49 | ]; 50 | 51 | return $config; 52 | } 53 | 54 | private function addVisibleAttributes(Product $simpleProduct, $jsonResult) 55 | { 56 | foreach ($simpleProduct->getAttributes() as $attribute) { 57 | if (($attribute->getIsVisible() && $attribute->getIsVisibleOnFront()) || in_array($attribute->getAttributeCode(), 58 | ['sku', 'description'])) { 59 | $code = $attribute->getAttributeCode(); 60 | $value = (string)$attribute->getFrontend()->getValue($simpleProduct); 61 | $jsonResult['dynamic'][$code][$simpleProduct->getId()] = [ 62 | 'value' => $value 63 | ]; 64 | } 65 | } 66 | 67 | return $jsonResult; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # magento2-configurable-sku-switch 2 | 3 | ### Status 4 | 5 | Tested by me on magento 2.1.3 (blank theme), works also on Magento 2.2 and Magento 2.3. 6 | 7 | Do not expect this module to be updated/bugg fixed/altered for any specific magento version 8 | 9 | ### Purpose 10 | Change data for configurable on frontend to show the data for selected product. 11 | 12 | ### Currently changed by default 13 | * sku 14 | * description 15 | * title (product name) 16 | * attributes tab 17 | 18 | #### Customize HTML-Attributes per simple product 19 | 20 | You can change text and attributes with this module. 21 | If nothing else is configured, it changes only the text. 22 | 23 | To add custom HTML-Attributes to elements, like css classes, you need to plugin 24 | `Magento\ConfigurableProduct\Block\Product\View\Type\Configurable` and `Magento\Swatches\Block\Product\Renderer\Configurable` 25 | with a method `afterGetJson` like so: 26 | 27 | ```php 28 | public function afterGetJsonConfig($subject, $result) 29 | { 30 | $jsonResult = json_decode($result, true); 31 | 32 | foreach ($subject->getAllowProducts() as $simpleProduct) { 33 | $id = $simpleProduct->getId(); 34 | $shippingCost = $this->getMyCustomValueForProduct(); 35 | $jsonResult['dynamic']['custom_extra_element_label'][$id] = [ 36 | 'value' => $shippingCost, 37 | 'attrs' => [ 38 | 'class' => 'some-css-class' 39 | ] 40 | ]; 41 | } 42 | 43 | $result = json_encode($jsonResult); 44 | return $result; 45 | } 46 | ``` 47 | 48 | #### Show whole blocks dynamically 49 | You can change whole blocks. 50 | 51 | **Preconditions:** 52 | * The block class MUST provide a method `setProduct()`. See `\Andering\ConfigurableDynamic\Block\Product\View\Attributes` for example 53 | * You must create a wrapper block and move the block into the wrapper. See: `view/frontend/layout/catalog_product_view.xml`for example 54 | 55 | Then you can create a plugin like `\Andering\ConfigurableDynamic\Plugin\Magento\ConfigurableProduct\Block\Product\View\Type\Configurable`. 56 | You have to inject `\Andering\ConfigurableDynamic\Helper\ConfigurableDynamicHelper` and call `addBlock()`. The method takes 5 parameter: 57 | 1. The dynamicDataId that you set on your wrapper block. E.g.: `product_attributes` 58 | 2. The blockId of the block you want to show dynamically. E.g.: `product.attributes` 59 | 3. The class of the block. E.g.: `\Andering\ConfigurableDynamic\Block\Product\View\Attributes::class` 60 | 4. The config array. 61 | 5. The simple product. 62 | 63 | ##### *credits:* 64 | [stachexchange](http://magento.stackexchange.com/questions/130128/magento-2-why-do-sku-not-change-dynamically-in-configurable-product-view-page/130148) 65 | 66 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "andering/magento2-configurable-dynamic", 3 | "description": "", 4 | "require": { 5 | 6 | }, 7 | "type": "magento2-module", 8 | "version": "0.1.0", 9 | "autoload": { 10 | "files": [ 11 | "registration.php" 12 | ], 13 | "psr-4": { 14 | "Andering\\ConfigurableDynamic\\": "" 15 | } 16 | }, 17 | "authors": [ 18 | { 19 | "name": "Andrej Kouril", 20 | "role": "Developer" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /etc/frontend/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /registration.php: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 20 9 | product_attributes 10 | 11 | 12 | 13 | 14 | 15 | 16 | data-dynamic="product_name" 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /view/frontend/requirejs-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by thomas on 2017-01-30. 3 | */ 4 | 5 | var config = { 6 | config: { 7 | mixins: { 8 | 'Magento_ConfigurableProduct/js/configurable': { 9 | 'Andering_ConfigurableDynamic/js/model/skuswitch': true 10 | }, 11 | 'Magento_Swatches/js/swatch-renderer': { 12 | 'Andering_ConfigurableDynamic/js/model/swatch-skuswitch': true 13 | } 14 | } 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /view/frontend/templates/block_wrap.phtml: -------------------------------------------------------------------------------- 1 | 2 |
hasData('html_class') ? 'class="' . $block->getData('html_class') . '"' : '' ?> 3 | data-dynamic="getData('dynamic_id') ?>"> 4 | getChildHtml() ?> 5 |
6 | -------------------------------------------------------------------------------- /view/frontend/web/js/model/skuswitch.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by thomas on 2017-01-30. 3 | */ 4 | 5 | define([ 6 | 'jquery', 7 | 'mage/utils/wrapper', 8 | 'mage/apply/main' 9 | ], function ($, wrapper, mage) { 10 | 'use strict'; 11 | return function(targetModule){ 12 | var reloadPrice = targetModule.prototype._reloadPrice; 13 | targetModule.prototype.dynamic = {}; 14 | targetModule.prototype.dynamicAttrs = []; 15 | 16 | $('[data-dynamic]').each(function(){ 17 | var code = $(this).data('dynamic'); 18 | var value = $(this).html(); 19 | var attrs = []; 20 | 21 | // Get the initial attributes value to be able to reset them if a user selects an option and then selects none again 22 | $.each(this.attributes, function() { 23 | attrs[this.name] = this.value; 24 | }); 25 | 26 | targetModule.prototype.dynamic[code] = value; 27 | targetModule.prototype.dynamicAttrs[code] = attrs; 28 | }); 29 | 30 | var reloadPriceWrapper = wrapper.wrap(reloadPrice, function(original){ 31 | var dynamic = this.options.spConfig.dynamic; 32 | 33 | for (var code in dynamic){ 34 | if (dynamic.hasOwnProperty(code)) { 35 | var value = ""; 36 | var attrs = []; 37 | var $placeholder = $('[data-dynamic='+code+']'); 38 | 39 | if(!$placeholder.length) { 40 | continue; 41 | } 42 | 43 | if(this.simpleProduct){ 44 | value = this.options.spConfig.dynamic[code][this.simpleProduct].value; 45 | attrs = this.options.spConfig.dynamic[code][this.simpleProduct].attrs; 46 | } else { 47 | value = this.dynamic[code]; 48 | attrs = this.dynamicAttrs[code]; 49 | } 50 | 51 | $placeholder.html(value); 52 | 53 | // Set all attributes if we have some 54 | if(attrs != undefined) { 55 | for(var a in attrs) { 56 | $placeholder.attr(a, attrs[a]); 57 | } 58 | } 59 | } 60 | } 61 | 62 | mage.apply(); 63 | 64 | return original(); 65 | }); 66 | 67 | targetModule.prototype._reloadPrice = reloadPriceWrapper; 68 | return targetModule; 69 | }; 70 | }); 71 | -------------------------------------------------------------------------------- /view/frontend/web/js/model/swatch-skuswitch.js: -------------------------------------------------------------------------------- 1 | /*jshint browser:true jquery:true*/ 2 | /*global alert*/ 3 | define([ 4 | 'jquery', 5 | 'mage/utils/wrapper', 6 | 'mage/apply/main' 7 | ], function ($, wrapper, mage) { 8 | 'use strict'; 9 | 10 | return function(targetModule){ 11 | 12 | var updatePrice = targetModule.prototype._UpdatePrice; 13 | targetModule.prototype.dynamic = {}; 14 | targetModule.prototype.dynamicAttrs = []; 15 | 16 | $('[data-dynamic]').each(function(){ 17 | var code = $(this).data('dynamic'); 18 | var value = $(this).html(); 19 | var attrs = []; 20 | 21 | // Get the initial attributes value to be able to reset them if a user selects an option and then selects none again 22 | $.each(this.attributes, function() { 23 | attrs[this.name] = this.value; 24 | }); 25 | 26 | targetModule.prototype.dynamic[code] = value; 27 | targetModule.prototype.dynamicAttrs[code] = attrs; 28 | }); 29 | 30 | var updatePriceWrapper = wrapper.wrap(updatePrice, function(original){ 31 | var dynamic = this.options.jsonConfig.dynamic; 32 | console.log(dynamic); 33 | for (var code in dynamic){ 34 | if (dynamic.hasOwnProperty(code)) { 35 | var value = ""; 36 | var attrs = []; 37 | var $placeholder = $('[data-dynamic='+code+']'); 38 | var allSelected = true; 39 | 40 | if(!$placeholder.length) { 41 | continue; 42 | } 43 | 44 | for(var i = 0; i