0

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?

  • Hi SO Community, Please guide me to achieve functionality. Thanks – Ankit Shah Oct 5 '16 at 2:20
2
+25

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:

  1. Create an after plugin for Magento\Checkout\CustomerData\ItemPool::getItemData() method
  2. Inside the returning array of product data I would add additional "type" attribute per product with value "A" or "B"
  3. Load Type attribute value as hidden form value on product page.
  4. 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:

    var cartData = customerData.get('cart');
    var items = cartData()['items'];
    var result = false;
    $.each(items, function(index, productItem) {
        if (productItem.type === productHiddenType) {
            result = true;
        }
    });
    if (result) {
        modalPopup.show(); //show form with Yes and No
    }
    
  5. Show popup with additional form

  6. Submit "Add to Cart" form in case customer clicks "Yes"
  7. Validation of Quote/Cart should happen on Quote::beforeSave plugin
  • Hi @Max. Thanks for your answer. Appreciated. I can understand what you are saying, but i'm not that much aware of Magento 2. Can you give your answer more precisely in which file, which code we can add step by sadi. So it works perfectly as per my requirement. Thanks – Ankit Shah Oct 10 '16 at 1:24
  • Sure, let me prepare it for you. – Max Pronko Oct 10 '16 at 21:10
  • Hi @Max Any updates? – Ankit Shah Oct 12 '16 at 1:30
  • Hi @Max Please give your updated answer – Ankit Shah Oct 21 '16 at 2:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.