I'm using Magento 2 CE Version 2.1.0.
I have a custom attribute called Type
with value A or B. User can only add 1 Product of Type A in the Cart.
If a user is going to Add Second time Same or Other product of Type A. Then Observer will give a message "This type of product is already exists. Would you like to overwrite?".
Able to display a message. Now I have to give 2 Buttons with a message "Yes" / "No". If clicked on "Yes" it will replace product in cart with current one & on "No" will do nothing.
app\code\Custom\Module\etc\frontend\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="controller_action_predispatch_checkout_cart_add">
<observer name="check_shopping_cart_page" instance="Custom\Module\Observer\CheckCartObserver" />
</event>
</config>
app\code\Custom\Module\Observer\CheckCartObserver.php
namespace Custom\Module\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\Request\DataPersistorInterface;
use Magento\Framework\App\ObjectManager;
class CheckCartObserver implements ObserverInterface {
protected $_urlManager;
protected $_checkoutSession;
protected $_cart;
protected $messageManager;
/**
* @var \Magento\Framework\App\Response\RedirectInterface
*/
protected $redirect;
public function __construct(
\Magento\Framework\UrlInterface $urlManager, \Magento\Checkout\Model\Session $checkoutSession, \Magento\Framework\App\Response\RedirectInterface $redirect, \Magento\Checkout\Model\Cart $cart, \Magento\Framework\Message\ManagerInterface $messageManager
) {
$this->_urlManager = $urlManager;
$this->_checkoutSession = $checkoutSession;
$this->redirect = $redirect;
$this->_cart = $cart;
$this->messageManager = $messageManager;
}
public function execute(\Magento\Framework\Event\Observer $observer) {
$actionName = $observer->getEvent()->getRequest()->getFullActionName();
$controller = $observer->getControllerAction();
$postValues = $controller->getRequest()->getPostValue();
$cartQuote = $this->_cart->getQuote()->getData();
// START IF YES CLICKED THEN REPLACE PRODUCT
if (isset($postValues['replaceYes'])) {
$this->messageManager->addError(__('Replace Yes Clicked'));
$this->redirect->redirect($controller->getResponse(), $this->redirect->getRefererUrl());
}
// STOP IF YES CLICKED THEN REPLACE PRODUCT
// START IF NO CLICKED THEN REPLACE PRODUCT
if (isset($postValues['replaceNo'])) {
$this->messageManager->addError(__('Replace No Clicked'));
$this->redirect->redirect($controller->getResponse(), $this->redirect->getRefererUrl());
}
// STOP IF NO CLICKED THEN REPLACE PRODUCT
// START TO CHECK IF TYPE A & ONLY 1 PRODUCT EXIST
$cartItemsCount = $this->_cart->getQuote()->getItemsCount();
$cartItemsAll = $this->_cart->getQuote()->getAllItems();
foreach ($cartItemsAll as $item) {
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$product = $objectManager->create('Magento\Catalog\Model\Product')->load($item->getProduct()->getId());
$type = $product->getAttributeText('type');
if ($type == 'A' && $cartItemsCount == 1) {
$this->messageManager->addError(__('A Type of product is already exist. Would you like to replace it? <form method="post"><input type="submit" name="replaceYes" value="Yes" /> <input type="submit" name="replaceNo" value="No" /></form>'));
$observer->getRequest()->setParam('product', false); // Will not add product to Cart
$this->redirect->redirect($controller->getResponse(), $this->redirect->getRefererUrl());
}
}
// END TO CHECK IF TYPE A & ONLY 1 PRODUCT EXIST
}
}
If this is not feasible, then what will be word around solution?
Best Answer
I do not recommend to attach an Observer to a controller_action_predispatch_checkout_cart_add event. Your requirement is more business-related than system/platform e.g. Session check or ACL/Permissions check so I wouldn't use controller observer.
Also, observer seems like responsible for lot's of things here: validation, request/response manipulations and html rendering.
My approach would be the following:
Create custom JavaScript component which will check "Add to Cart" submit event and verify if hidden Type attribute value appears to be in the list of existing products added to a cart:
Show popup with additional form