Today we’d like to introduce the method of displaying the shopping cart’s sidebar after adding the product to the cart in Magento® 2. We are going to use AJAX for these purposes. You can also customize your online store’s shopping cart by performing this method if your shop is based on Magento.
Now Magento 2 has got a quite useful out-of-box feature: adding the product to the shopping cart with AJAX. You can turn on this option on the store setting page. This option works with all the products which don’t have file options.
Our task is to display the sidebar for a while after adding a product to the shopping cart. Here, the sidebar is a shopping cart block placed in the page title. We recommend you the specific module for doing this task.
<div class="ufy-block">
<div class="ufy-block__wrapper">
<p class="ufy-block__label">Useful for you:</p>
<ul class="ufy-block__list">
<li class="ufy-block__item"><a href="https://web4pro.net/blog-news/extension-attributes-for-total-model-in-magento-2/" target="_self" rel="noopener" data-wpel-link="internal">Extension Attributes for Total Model in Magento 2</a></li>
</ul>
</div>
</div>
Sidebar Implementation for Shopping Cart in Magento 2
Today we want to share the way how to solve this problem with our Magento AJAX tutorial. In Magento 2, the shopping cart is formed with a JavaScript plugin called the Knockout. The process is based on the shopping cart data which returns from the server with AJAX in JSON form. The browser stores these data until the next update. getSectionData() method of \Magento\Checkout\CustomerData\Cart class provides this JSON.
Let’s take a look at its implementation:
public function getSectionData()
{
$totals = $this->getQuote()->getTotals();
return [
'summary_count' => $this->getSummaryCount(),
'subtotal' => isset($totals['subtotal'])
? $this->checkoutHelper->formatPrice($totals['subtotal']->getValue())
: 0,
'possible_onepage_checkout' => $this->isPossibleOnepageCheckout(),
'items' => $this->getRecentItems(),
'extra_actions' => $this->layout->createBlock('Magento\Catalog\Block\ShortcutButtons')->toHtml(),
'isGuestCheckoutAllowed' => $this->isGuestCheckoutAllowed(),
'website_id' => $this->getQuote()->getStore()->getWebsiteId()
];
}
We should pay close attention to ‘extra_actions’ array element. It’s used for adding extra buttons to the sidebar, such as PayPal Express Checkout. But you can also add any block there, which implements \Magento\Catalog\Block\ShortcutInterface interface.
Step 1. Set up Delay Time Configuration
So let’s start. I’ll pass out creating registration.php and etc/module.xml files. We need these files only for registering the module. First, we set up delay time configuration using etc/adminhtml/system.xml file. Here is how it works:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
<system>
<section id="web4pro_ajaxcart"translate="label"sortOrder="10"showInDefault="1"showInWebsite="1"showInStore="1">
<label>Ajax Cart</label>
<tab>mg_extensions</tab>
<resource>WEB4PRO_Ajaxcart::config</resource>
<group id="general" translate="label" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1">
<label>General</label>
<field id="cart_add_delay" translate="label comment" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Cart Add Popup Delay</label>
</field>
</group>
</section>
</system>
</config>
We should set the default value in the etc/config.xml module. Let’s take a 1 second as the default delay time.
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Store/etc/config.xsd">
<default>
<web4pro_ajaxcart>
<general>
<cart_add_delay>1</cart_add_delay>
</general>
</web4pro_ajaxcart>
</default>
</config>
Step 2. Implementation of the Handlers for Two Events
Now we need to implement the handlers for two events. The first event is checkout_cart_add_product_complete which happens when the user successfully adds the product to the shopping cart. The second one is shortcut_buttons_container which can help us add the child block to the ‘extra_actions’ block. Let’s describe these events in the etc/events.xml file:
<?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="shortcut_buttons_container">
<observer name="ajaxcart" instance="Web4pro\Ajaxcart\Observer\Addshortcut" shared="false" />
</event>
<event name="checkout_cart_add_product_complete">
<observer name="ajaxcart" instance="Web4pro\Ajaxcart\Observer\Addproduct" shared="false" />
</event>
</config>
WEB4PRO\Ajaxcart\Observer\Addproduct class has the following implementation:
namespace Web4pro\Ajaxcart\Observer;
class Addproduct implements \Magento\Framework\Event\ObserverInterface {
protected $_checkoutSession;
public function __construct(\Magento\Checkout\Model\Session $session){
$this->_checkoutSession = $session;
}
public function execute(\Magento\Framework\Event\Observer $observer){
$this->_checkoutSession->setShowCart(true);
}
}
As you can see, we get Magento\Checkout\Model\Session object in observer’s constructor. So if it’s processed successfully, we’ll set the session variable to ‘true’. It is necessary to do because in Magento 2, adding a product to the shopping cart and reloading the sidebar content always work in different AJAX requests from the browser to the server.
Step 3. Shortcut.phtml Block’s Template
Now, look at the jQuery AJAX request example. We implement WEB4PRO\Ajaxcart\Observer\Addshortcut class the next way:
namespace Web4pro\Ajaxcart\Observer;
class Addshortcut implements \Magento\Framework\Event\ObserverInterface {
public function execute(\Magento\Framework\Event\Observer $observer){
if($container = $observer->getEvent()->getContainer()){
if($container->getRequest()->isAjax()){
$block = $container->getLayout()->createBlock('\Web4pro\Ajaxcart\Block\Shortcut')
->setTemplate('Web4pro_Ajaxcart::shortcut.phtml');
$container->addShortcut($block);
}
}
}
}
The container is a Magento\Catalog\Block\ShortcutButtons block where we place our child block using the addShortuct method. The block must implement \Magento\Catalog\Block\ShortcutInterface. Otherwise, it won’t be added. This event is triggered before the rendering Magento\Catalog\Block\ShortcutButtons block in the _beforeToHtml() method.
Let’s look at the \WEB4PRO\Ajaxcart\Block\Shortcut class implementation.
namespace Web4pro\Ajaxcart\Block;
class Shortcut extends \Magento\Checkout\Block\Cart\AbstractCart implements \Magento\Catalog\Block\ShortcutInterface {
public function getAlias(){
return 'cart_delay';
}
public function getCacheKeyInfo()
{
$result = parent::getCacheKeyInfo();
$result[] = $this->_checkoutSession->getShowCart();
return $result;
}
protected function _toHtml(){
if($this->_checkoutSession->getShowCart()&&$this->getRequest()->getActionName()=='load'){
$this->_checkoutSession->setShowCart(false);
return parent::_toHtml();
}
return '';
}
public function getDelay(){
return 1000*$this->_scopeConfig->getValue('magentice_ajaxcart/general/cart_add_delay');
}
}
Used Methods
getDelay() method returns the loading time value in milliseconds.
getAlias() method allows us to implement \Magento\Catalog\Block\ShortcutInterface.
In __toHtml() method, we set the flag of displaying block to ‘false’ right after the output to avoid repeated block output and also implement its display only on the sidebar.
getCacheKeyInfo() method allows us to save the various blocks variants to the cache: a block with output and without one.
shortut.phtml block’s template looks the following way:
<script type="text/javascript">
require(['Magento_Customer/js/customer-data'],function(customerData){
customerData.reload(["cart"],false);
});
jQuery('.minicart-wrapper').addClass('active');
jQuery('.minicart-wrapper a').first().addClass('active');
jQuery('.minicart-wrapper div').first().show();
setTimeout(function(){
jQuery('.minicart-wrapper a').first().removeClass('active');
jQuery('.minicart-wrapper div').first().hide();
jQuery('.minicart-wrapper').removeClass('active');
},<?php echo $this->getDelay(); ?>);
</script>
As you can see, this template content is just JavaScript. First, we set “active” class on the sidebar elements for displaying this class. After the timeout, we remove the class in order to hide the sidebar. The first-row code carries out cart content reload from the server.
You can use the shortcut block to place any other custom blocks to the sidebar.
<div class="ufy-block">
<div class="ufy-block__wrapper">
<p class="ufy-block__label">Useful for you:</p>
<ul class="ufy-block__list">
<li class="ufy-block__item"><a href="https://web4pro.net/blog-news/using-negative-values-product-quantity-in-magento-2/" target="_self" rel="noopener" data-wpel-link="internal">Using Negative Values for the Product Quantity in Magento 2</a></li>
<li><a href="https://web4pro.net/blog-news/pricing-rules-in-magento-2/" target="_self" rel="noopener" data-wpel-link="internal">Creating Pricing Rules in Magento 2 Using Amasty_RulesPro</a></li>
</ul>
</div>
</div>