Hello Magento Friends In this Blog Post i'm Share with to How to Add Custom Product Option Data SHow on mini cart in magento
this Custom Product Option show on mini cart , cart, checkout, sales order view, invoice new, invoice view and invoice pdf
👉 Step 1: Create a events.xml file in VendorName/ModuleName/etc/events.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="checkout_cart_product_add_after">
<observer name="mageget_checkout_cart_product_add_after"
instance="Dww\Quote\Observer\CheckoutCartAdd"/>
</event>
<event name="sales_model_service_quote_submit_before">
<observer name="mageget_add" instance="Dww\Quote\Observer\AddOptionToOrder"/>
</event>
</config>
👉 Step2 : Create a CheckoutCartAdd.php file in VendorName/ModuleName/Observer/CheckoutCartAdd.php
<?php
namespace Dww\Quote\Observer;
use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\View\LayoutInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Serialize\SerializerInterface;
class CheckoutCartAdd implements ObserverInterface
{
protected $layout;
protected $storeManager;
protected $request;
private $serializer;
public function __construct(
StoreManagerInterface $storeManager,
LayoutInterface $layout,
RequestInterface $request,
\Magento\Framework\Serialize\Serializer\Json $json,
SerializerInterface $serializer
)
{
$this->layout = $layout;
$this->storeManager = $storeManager;
$this->request = $request;
$this->json = $json;
$this->serializer = $serializer;
}
public function execute(EventObserver $observer)
{
$item = $observer->getQuoteItem();
$post = $this->request->getPost();
$writer = new \Zend_Log_Writer_Stream(BP . '/var/log/custom.log');
$logger = new \Zend_Log();
$logger->addWriter($writer);
$customedata = array();
if ($additionalOption = $item->getOptionByCode('additional_options')) {
$customedata = $this->serializer->unserialize($additionalOption->getValue());
}
$part= '{"face": "#FFF333", "Accent": "#f00","Deepak": "#46F300","Mageget": "#0007F3"}';
$color = "";
$jsonDecode = $this->json->unserialize($part);
$customedata[] = [
'label' => 'Customized Parts',
'value' => $part,
];
if (count($customedata) > 0) {
$item->addOption(array(
'product_id' => $item->getProductId(),
'code' => 'additional_options',
'value' => $this->serializer->serialize($customedata)
));
}
}
}
👉 Step3: Create a AddOptionToOrder.php file in VendorName/ModuleName/Observer/AddOptionToOrder.php
<?php
namespace Dww\Quote\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Serialize\SerializerInterface;
class AddOptionToOrder implements ObserverInterface
{
private $serializer;
public function __construct(
SerializerInterface $serializer
){
$this->serializer = $serializer;
}
public function execute(\Magento\Framework\Event\Observer $observer)
{
$writer = new \Zend_Log_Writer_Stream(BP . '/var/log/custom.log');
$logger = new \Zend_Log();
$logger->addWriter($writer);
$quote = $observer->getQuote();
$order = $observer->getOrder();
foreach ($quote->getAllVisibleItems() as $quoteItem) {
$quoteItems[$quoteItem->getId()] = $quoteItem;
}
foreach ($order->getAllVisibleItems() as $orderItem) {
$quoteItemId = $orderItem->getQuoteItemId();
$quoteItem = $quoteItems[$quoteItemId];
$additionalOptions = $quoteItem->getOptionByCode('additional_options');
$logger->info(print_r($additionalOptions->getValue(), true)); //To print array log
if (count(array($additionalOptions)) > 0) {
$options = $orderItem->getProductOptions();
$options['additional_options'] = $this->serializer->unserialize($additionalOptions->getValue());
$orderItem->setProductOptions($options);
}
}
return $this;
}
}
👉 Step4: Create a requirejs-config.js file in app\code\VendorName\ModuleName\view\frontend\requirejs-config.js
var config = {
map: {
'*': {
'Magento_Checkout/template/minicart/item/default.html':
'Dww_Quote/template/minicart/item/default.html'
}
}
};
Step5: create a default.html file in app\code\VendorName\ModuleName\view\frontend\web\template\minicart\item\default.html
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<li class="item product product-item" data-role="product-item">
<div class="product">
<!-- ko if: product_has_url -->
<a data-bind="attr: {href: product_url, title: product_name}" tabindex="-1" class="product-item-photo">
<!-- ko foreach: $parent.getRegion('itemImage') -->
<!-- ko template: {name: getTemplate(), data: item.product_image} --><!-- /ko -->
<!-- /ko -->
</a>
<!-- /ko -->
<!-- ko ifnot: product_has_url -->
<span class="product-item-photo">
<!-- ko foreach: $parent.getRegion('itemImage') -->
<!-- ko template: {name: getTemplate(), data: item.product_image} --><!-- /ko -->
<!-- /ko -->
</span>
<!-- /ko -->
<div class="product-item-details">
<strong class="product-item-name">
<!-- ko if: product_has_url -->
<a data-bind="attr: {href: product_url}, html: $parent.getProductNameUnsanitizedHtml(product_name)"></a>
<!-- /ko -->
<!-- ko ifnot: product_has_url -->
<span data-bind="html: $parent.getProductNameUnsanitizedHtml(product_name)"></span>
<!-- /ko -->
</strong>
<!-- ko if: options.length -->
<div class="product options" data-mage-init='{"collapsible":{"openedState": "active", "saveState": false}}'>
<span data-role="title" class="toggle"><!-- ko i18n: 'See Details' --><!-- /ko --></span>
<div data-role="content" class="content">
<strong class="subtitle"><!-- ko i18n: 'Options Details' --><!-- /ko --></strong>
<dl class="product options list">
<!-- ko foreach: { data: options, as: 'option' } -->
<dt class="label"><!-- ko text: option.label --><!-- /ko --></dt>
<dd class="values">
<!-- ko if: Array.isArray(option.value) -->
<span data-bind="html: $parents[1].getOptionValueUnsanitizedHtml(option.value.join('<br/>'))"></span>
<!-- /ko -->
<!-- ko if: (!Array.isArray(option.value) && ['file', 'html'].includes(option.option_type)) -->
<span data-bind="html: $parents[1].getOptionValueUnsanitizedHtml(option.value)"></span>
<!-- /ko -->
<!-- ko if: (!Array.isArray(option.value) && !['file', 'html'].includes(option.option_type)) -->
<!-- ko foreach: {data: JSON.parse(option.value), as: '_task' } -->
<table>
<tbody>
<tr>
<td>
<!-- ko foreach:{data: Array(Object.keys(_task)), as: 'colorkeys' } -->
<div data-bind="foreach: $data ">
<div data-bind="style:{margin:'4px 0px'}">
<span data-bind="html: colorkeys[$index()]"> </span> :<br/>
</div>
</div>
<!-- /ko -->
</td>
<td>
<!-- ko foreach:{data: Array(Object.values(_task)), as: 'colorvalues' } -->
<div data-bind="foreach: $data ">
<div data-bind="style:{width:'70px',margin:'4px 0px',background:colorvalues[$index()]}">
<span data-bind="html: colorvalues[$index()]"> </span><br/>
</div>
</div>
<!-- /ko -->
</td>
</tr>
</tbody>
</table>
<!-- /ko -->
<!-- /ko -->
</dd>
<!-- /ko -->
</dl>
</div>
</div>
<!-- /ko -->
<div class="product-item-pricing">
<!-- ko if: canApplyMsrp -->
<div class="details-map">
<span class="label" data-bind="i18n: 'Price'"></span>
<span class="value" data-bind="i18n: 'See price before order confirmation.'"></span>
</div>
<!-- /ko -->
<!-- ko ifnot: canApplyMsrp -->
<!-- ko foreach: $parent.getRegion('priceSidebar') -->
<!-- ko template: {name: getTemplate(), data: item.product_price, as: 'price'} --><!-- /ko -->
<!-- /ko -->
<!-- /ko -->
<div class="details-qty qty">
<label class="label" data-bind="i18n: 'Qty', attr: {
for: 'cart-item-'+item_id+'-qty'}"></label>
<input data-bind="attr: {
id: 'cart-item-'+item_id+'-qty',
'data-cart-item': item_id,
'data-item-qty': qty,
'data-cart-item-id': product_sku
}, value: qty"
type="number"
size="4"
class="item-qty cart-item-qty"/>
<button data-bind="attr: {
id: 'update-cart-item-'+item_id,
'data-cart-item': item_id,
title: $t('Update')
}"
class="update-cart-item"
style="display: none">
<span data-bind="i18n: 'Update'"></span>
</button>
</div>
</div>
<div class="product actions">
<!-- ko if: is_visible_in_site_visibility -->
<div class="primary">
<a data-bind="attr: {href: configure_url, title: $t('Edit item')}" class="action edit">
<span data-bind="i18n: 'Edit'"></span>
</a>
</div>
<!-- /ko -->
<div class="secondary">
<a href="#" data-bind="attr: {'data-cart-item': item_id, title: $t('Remove item')}"
class="action delete">
<span data-bind="i18n: 'Remove'"></span>
</a>
</div>
</div>
</div>
</div>
<div class="message notice" if="$data.message">
<div data-bind="text: $data.message"></div>
</div>
</li>