How to display swatches like color and size option with the frame instead of plain text name of the item on checkout. it will most certainly work on the better experience of our website.
Magento2 contains the component used to display the details of a cart item
Magento_Checkout/js/view/summary/item/details, so we will need to overwrite its *.js or *.html files. Following are the steps.
Read This:How To Programmatically Assign Products To Multiple Categories In Magento 2
so create its required files and give the module name Dolphin_CheckoutSwatches
File Path: app/code/Dolphin/CheckoutSwatches/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="Dolphin_CheckoutSwatches" setup_version="0.1.0"> <sequence> <module name="Magento_Swatches"/> <module name="Magento_Checkout"/> </sequence> </module> </config>
File Path: app/code/Dolphin/CheckoutSwatches/registration.php
<?php use Magento\Framework\Component\ComponentRegistrar; ComponentRegistrar::register( ComponentRegistrar::MODULE, 'Dolphin_CheckoutSwatches', __DIR__ );
After creating the module first of all focus on the swatch layout for this we need to create LayoutProcessor using dependency injection.
File Path: app/code/Dolphin/CheckoutSwatches/Model/Swatches/LayoutProcessor.php
<?php namespace Dolphin\CheckoutSwatches\Model\Swatches; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Serialize\Serializer\Json; use Magento\Quote\Api\Data\CartItemInterface; use Magento\Swatches\Block\Product\Renderer\ConfigurableFactory; use Magento\Checkout\Model\Session; /** * Class LayoutProcessor * * This class is responsible for getting swatches js layout for every cart item to render swatches on checkout. */ class LayoutProcessor { /** * @var Json $json */ private $json; /** * @var ConfigurableFactory $configurableFactory */ private $configurableFactory; /** * @var Session $session */ private $session; /** * LayoutProcessor constructor. * * @param Json $json * @param ConfigurableFactory $configurableFactory * @param Session $session */ public function __construct( Json $json, ConfigurableFactory $configurableFactory, Session $session ) { $this->json = $json; $this->configurableFactory = $configurableFactory; $this->session = $session; } /** * @return array * @throws LocalizedException * @throws NoSuchEntityException */ public function getJsLayout() { $jsLayout = []; foreach ($this->session->getQuote()->getItems() as $item) { $isConfigurable = $item->getProductType() == Configurable::TYPE_CODE; $jsLayout[$item->getItemId()] = [ 'jsonConfig' => $isConfigurable ? $this->getJsonConfig($item) : null, 'jsonSwatchConfig' => $isConfigurable ? $this->getJsonSwatchConfig($item) : null ]; } return $jsLayout; } /** * @param CartItemInterface $item * @return string */ private function getJsonConfig(CartItemInterface $item) { $configurable = $this->configurableFactory->create() ->setProduct($item->getProduct()); return $configurable->getJsonConfig(); } /** * @param CartItemInterface $item * @return string */ private function getJsonSwatchConfig(CartItemInterface $item) { $configurable = $this->configurableFactory->create() ->setProduct($item->getProduct()); return $this->filterJsonSwatchConfig($configurable->getJsonSwatchConfig(), $item); } /** * @param CartItemInterface $item * @return array */ private function getOptions(CartItemInterface $item) { $output = []; $options = $item->getProduct()->getTypeInstance()->getOrderOptions($item->getProduct()); $attributesInfo = $options['attributes_info']; if (!empty($attributesInfo)) { foreach ($attributesInfo as $info) { $output[] = $info['value']; } } return $output; } /** * @param string $jsonSwatchConfig * @param CartItemInterface $item * @return string */ private function filterJsonSwatchConfig(string $jsonSwatchConfig, CartItemInterface $item) { $output = []; $options = $this->getOptions($item); foreach ($this->json->unserialize($jsonSwatchConfig) as $primary => $config) { foreach ($config as $secondary => $option) { if (is_array($option) && in_array($option['label'], $options)) { $output[$primary][$secondary] = $option; } } } return $this->json->serialize($output); } }
Let’s take a look at the functions of this class.
1. getJsLayout–> It returns an array of data needed to run the swatch renderer on the front end. This array contains information about each item in the shopping cart. These items are stored in the session.
2. getJsonConfig –> function returns the main configuration of a given product. It contains all possible swatch options, their asset paths, etc. In the absence of product options (the product is not configurable), it returns null.
3. getJsonSwatchConfig –> function returns the configuration of the selected option when it is added to the shopping cart. It gets the configuration of all available options and then filters them to keep only the options selected by the user.
So, if we don’t filter this array on the front end, we will see that all available product options are swatches!
4. filterJsonSwatchConfig –> function filters the input JSON configuration of the sample. The output array only accepts the options selected by the user. This happens through the array returned by the getOptions function.
Comparing the label with the returned option value can be confusing. But this is not an error. This is all because the color value is stored in the option by its name, such as Purple, in the configuration, it is in the hexadecimal system, such as #800080. Therefore, we must map a value from the label. In the case of size, it doesn’t matter. These two fields have the same value. In this way, we received the correct configuration of the swatch renderer for each product in the shopping cart.
Now we need to focus on the plugin it injects the result of calling the getJsLayout function from the previously created processor class for swatches.
File Path: app/code/Dolphin/CheckoutSwatches/Plugin/Checkout/Block/Checkout/LayoutProcessor.php
<?php namespace Dolphin\CheckoutSwatches\Plugin\Checkout\Block\Checkout; use Dolphin\CheckoutSwatches\Model\Swatches\LayoutProcessor as SwatchesLayoutProcessor; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\NoSuchEntityException; /** * Class LayoutProcessor * * This class is a plugin for Checkout LayoutProcessor to add swatches JSON configs to details Ui Component. */ class LayoutProcessor { /** * @var SwatchesLayoutProcessor $swatchesLayoutProcessor */ private $swatchesLayoutProcessor; /** * LayoutProcessor constructor. * * @param SwatchesLayoutProcessor $swatchesLayoutProcessor */ public function __construct(SwatchesLayoutProcessor $swatchesLayoutProcessor) { $this->swatchesLayoutProcessor = $swatchesLayoutProcessor; } /** * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $subject * @param array $result * @return mixed * @throws LocalizedException * @throws NoSuchEntityException */ public function afterProcess(\Magento\Checkout\Block\Checkout\LayoutProcessor $subject, array $result) { $result['components']['checkout']['children']['sidebar']['children']['summary']['children']['cart_items'] ['children']['details']['config']['swatchesJsLayout'] = $this->swatchesLayoutProcessor->getJsLayout(); return $result; } }
File Path: app/code/Dolphin/CheckoutSwatches/etc/frontend/di.xml
so the final di.xml will look like the below,
<?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="Dolphin\CheckoutSwatches\Model\Swatches\LayoutProcessor"> <arguments> <argument name="session" xsi:type="object">Magento\Checkout\Model\Session\Proxy</argument> </arguments> </type> <type name="Magento\Checkout\Block\Checkout\LayoutProcessor"> <plugin name="dolphin_checkout_swatches_layout_processor_plugin" type="Dolphin\CheckoutSwatches\Plugin\Checkout\Block\Checkout\LayoutProcessor" sortOrder="10"/> </type> </config>
Since the product options are displayed in the Magento_Checkout/summary/item/details template, we need to inject the configuration into the UI Component details.
File Path: app/code/Dolphin/CheckoutSwatches/view/frontend/web/js/view/summary/item/details.js
define([], function () { var mixin = { defaults: { template: 'Dolphin_CheckoutSwatches/summary/item/details', }, getSwatchesJsLayoutByItemId: function (itemId) { return this.swatchesJsLayout[itemId]; } }; return function (Component) { return Component.extend(mixin); }; });
File Path: app/code/Dolphin/CheckoutSwatches/view/frontend/web/template/summary/item/details.html
<!-- ko foreach: getRegion('before_details') --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> <div class="product-item-details"> <div class="product-item-inner"> <div class="product-item-name-block"> <strong class="product-item-name" data-bind="html: $parent.name"></strong> <div class="details-qty"> <span class="label"><!-- ko i18n: 'Qty' --><!-- /ko --></span> <span class="value" data-bind="text: $parent.qty"></span> </div> </div> <!-- ko foreach: getRegion('after_details') --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> </div> <!-- ko if: (JSON.parse($parent.options).length > 0)--> <div class="product options" data-bind="mageInit: {'collapsible':{'openedState': 'active'}}"> <span data-role="title" class="toggle"><!-- ko i18n: 'View Details' --><!-- /ko --></span> <div data-role="content" class="content"> <strong class="subtitle"><!-- ko i18n: 'Options Details' --><!-- /ko --></strong> <!-- ko if: (getSwatchesJsLayoutByItemId($parent.item_id))--> <div data-bind='mageInit: { "Magento_Swatches/js/swatch-renderer": { "jsonConfig": JSON.parse(getSwatchesJsLayoutByItemId($parent.item_id).jsonConfig), "jsonSwatchConfig": JSON.parse(getSwatchesJsLayoutByItemId($parent.item_id).jsonSwatchConfig) } }'></div> <!-- /ko --> </div> </div> <!-- /ko --> </div> <!-- ko foreach: getRegion('item_message') --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko -->
We should begin by making a mixin for the UI component details. We can and we will define the *.html template directly from the *.js file. Alternatively, we could create a checkout_index_index.xml file in the view/frontend/layout catalog and inject the details template into the config like this:
File Path: app/code/Dolphin/CheckoutSwatches/view/frontend/layout/checkout_index_index.xml
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="content"> <referenceBlock name="checkout.root"> <arguments> <argument name="jsLayout" xsi:type="array"> <item name="components" xsi:type="array"> <item name="checkout" xsi:type="array"> <item name="children" xsi:type="array"> <item name="sidebar" xsi:type="array"> <item name="children" xsi:type="array"> <item name="summary" xsi:type="array"> <item name="children" xsi:type="array"> <item name="cart_items" xsi:type="array"> <item name="children" xsi:type="array"> <item name="details" xsi:type="array"> <item name="config" xsi:type="array"> <item name="template" xsi:type="string">Dolphin_CheckoutSwatches/summary/item/details</item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </argument> </arguments> </referenceBlock> </referenceContainer> </body> </page>
File Path: app/code/Dolphin/CheckoutSwatches/view/frontend/requirejs-config.js
var config = { config: { 'mixins': { 'Magento_Checkout/js/view/summary/item/details': { 'Dolphin_CheckoutSwatches/js/view/summary/item/details': true } } } };
That’s it. Happy Coding with magento2!! ? Feel free to comment if you have any issue.