Question

I want to pass my custom_price changed via jQuery to my Observer in Magento 2 to have the correct price in my cart.

My /Observer/CustomPrice.php:

<?php
    namespace Vendor_Name\Module_Name\Observer;

    use Magento\Framework\Event\ObserverInterface;
    use Magento\Framework\App\RequestInterface;

    class CustomPrice implements ObserverInterface
    {
        public function execute(\Magento\Framework\Event\Observer $observer) {
            $item = $observer->getEvent()->getData('quote_item');         
            $item = ( $item->getParentItem() ? $item->getParentItem() : $item );
            $price = 123; // CUSTOM_PRICE variable HERE instead of "123"
            $item->setCustomPrice($price);
            $item->setOriginalCustomPrice($price);
            $item->getProduct()->setIsSuperMode(true);
        }

    }
?>

Excerpt of my JS script /view/frontend/web/product.js:

require([ 'jquery'], function($){
$(document).ready(function () {

//... price calculations
custom_price = price + product_attribute_value
$("#custom_price").html(custom_price);

};
};

Edit for completion: My 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="checkout_cart_product_add_after">
        <observer name="customprice" instance="Vendor_Name\Module_Name\Observer\CustomPrice" />
    </event>
</config>

My question is: How to replace the "123" value within the observer with my "custom_price" value from the jQuery calculations? (I know this is not the safest way to build up this thing on client site, but it should be fine since every price is getting checked manually after customer checkout).

Further comments:

  1. The Observer is working fine with "123"
  2. Using Magento 2.1.3

I also have a working extension for Magento 2.1 which does this without any Observer (only Controller/Cart/Add.php). I have still no clue how this is possible - trying to learn M2. After my update to 2.1.3 the functionality stopped working. An observer seems to be the right way to go for me. What do you think?


First attempt on Khoas answer: (Thanks for the fast reply!)

My /view/frontend/templates/block.phtml:

<form>
 <input type="hidden" name="custom_price" value="" id="custom_price_cal">
</form>

Excerpt of my JS Script /view/frontend/web/product.js:

require([ 'jquery'], function($){
$(document).ready(function () {

//... price calculations

var price =  90;
var product_attribute_value = 430;
custom_price = price + product_attribute_value;
console.log(custom_price);
$('#custom_price_cal').val(custom_price);

});
});

My /Observer/CustomPrice.php:

<?php

    namespace Vendor_Name\Module_Name\Observer;

    use Magento\Framework\Event\ObserverInterface;
    use Magento\Framework\App\RequestInterface;

    class CustomPrice implements ObserverInterface
    {
        public function __construct(
    \Magento\Framework\App\RequestInterface $request
    )
    {
        $this->_request = $request;
    }

        public function execute(\Magento\Framework\Event\Observer $observer) {
            $item = $observer->getEvent()->getData('quote_item');         
            $item = ( $item->getParentItem() ? $item->getParentItem() : $item );
            $price = $this->_request->getParam('custom_price');
            $item->setCustomPrice($price);
            $item->setOriginalCustomPrice($price);
            $item->getProduct()->setIsSuperMode(true);
        }

    }
?>

Making these changes the custom_price does not appear in cart right now. What am I missing out?


My /Controller/Cart/Add.php (how it has worked in 2.1)

<?php
/**
 *
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Vendor_Name\Module_Name\Controller\Cart;

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Checkout\Model\Cart as CustomerCart;
use Magento\Framework\Exception\NoSuchEntityException;

/**
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class Add extends \Magento\Checkout\Controller\Cart
{
    /**
     * @var ProductRepositoryInterface
     */
    protected $productRepository;

    /**
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
     * @param \Magento\Checkout\Model\Session $checkoutSession
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator
     * @param CustomerCart $cart
     * @param ProductRepositoryInterface $productRepository
     * @codeCoverageIgnore
     */
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        \Magento\Checkout\Model\Session $checkoutSession,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator,
        CustomerCart $cart,
        ProductRepositoryInterface $productRepository
    ) {
        parent::__construct(
            $context,
            $scopeConfig,
            $checkoutSession,
            $storeManager,
            $formKeyValidator,
            $cart
        );
        $this->productRepository = $productRepository;
    }

    /**
     * Initialize product instance from request data
     *
     * @return \Magento\Catalog\Model\Product|false
     */
    protected function _initProduct()
    {
        $productId = (int)$this->getRequest()->getParam('product');
        if ($productId) {
            $storeId = $this->_objectManager->get('Magento\Store\Model\StoreManagerInterface')->getStore()->getId();
            try {
                return $this->productRepository->getById($productId, false, $storeId);
            } catch (NoSuchEntityException $e) {
                return false;
            }
        }
        return false;
    }

    /**
     * Add product to shopping cart action
     *
     * @return \Magento\Framework\Controller\Result\Redirect
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     */
    public function execute()
    {
        if (!$this->_formKeyValidator->validate($this->getRequest())) {
            return $this->resultRedirectFactory->create()->setPath('*/*/');
        }

        $params = $this->getRequest()->getParams();
        $params['custom_price']= $params['custom_final_price'];
        try {
            if (isset($params['qty'])) {
                $filter = new \Zend_Filter_LocalizedToNormalized(
                    ['locale' => $this->_objectManager->get('Magento\Framework\Locale\ResolverInterface')->getLocale()]
                );
                $params['qty'] = $filter->filter($params['qty']);
            }

            $product = $this->_initProduct();
            $related = $this->getRequest()->getParam('related_product');

            /**
             * Check product availability
             */
            if (!$product) {
                return $this->goBack();
            }

            $this->cart->addProduct($product, $params);
            if (!empty($related)) {
                $this->cart->addProductsByIds(explode(',', $related));
            }

            $this->cart->save();

            /**
             * @todo remove wishlist observer \Magento\Wishlist\Observer\AddToCart
             */
            $this->_eventManager->dispatch(
                'checkout_cart_add_product_complete',
                ['product' => $product, 'request' => $this->getRequest(), 'response' => $this->getResponse()]
            );

            if (!$this->_checkoutSession->getNoCartRedirect(true)) {
                if (!$this->cart->getQuote()->getHasError()) {
                    $message = __(
                        'You added %1 to your shopping cart.',
                        $product->getName()
                    );
                    $this->messageManager->addSuccessMessage($message);
                }
                return $this->goBack(null, $product);
            }
        } catch (\Magento\Framework\Exception\LocalizedException $e) {
            if ($this->_checkoutSession->getUseNotice(true)) {
                $this->messageManager->addNotice(
                    $this->_objectManager->get('Magento\Framework\Escaper')->escapeHtml($e->getMessage())
                );
            } else {
                $messages = array_unique(explode("\n", $e->getMessage()));
                foreach ($messages as $message) {
                    $this->messageManager->addError(
                        $this->_objectManager->get('Magento\Framework\Escaper')->escapeHtml($message)
                    );
                }
            }

            $url = $this->_checkoutSession->getRedirectUrl(true);

            if (!$url) {
                $cartUrl = $this->_objectManager->get('Magento\Checkout\Helper\Cart')->getCartUrl();
                $url = $this->_redirect->getRedirectUrl($cartUrl);
            }

            return $this->goBack();

        } catch (\Exception $e) {
            $this->messageManager->addException($e, __('We can\'t add this item to your shopping cart right now.'));
            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
            return $this->goBack();
        }
    }

    /**
     * Resolve response
     *
     * @param string $backUrl
     * @param \Magento\Catalog\Model\Product $product
     * @return $this|\Magento\Framework\Controller\Result\Redirect
     */
    protected function goBack($backUrl = null, $product = null)
    {
        if (!$this->getRequest()->isAjax()) {
            return parent::_goBack($backUrl);
        }

        $result = [];

        if ($backUrl || $backUrl = $this->getBackUrl()) {
            $result['backUrl'] = $backUrl;
        } else {
            if ($product && !$product->getIsSalable()) {
                $result['product'] = [
                    'statusText' => __('Out of stock')
                ];
            }
        }

        $this->getResponse()->representJson(
            $this->_objectManager->get('Magento\Framework\Json\Helper\Data')->jsonEncode($result)
        );
    }
}

I haven't done any changes here. Instead I've created " /Observer/CustomPrice.php" to make it work for Magento 2.1.3 which you see above. The /Controller/Cart/Add.php has been copied from "/vendor/magento/module-checkout/Controller/Cart/Add.php" and only one line had been added:

$params['custom_price']= $params['custom_final_price']; 

Solution for my issue on how to pass jQuery value to Observer (into my Mini-Cart):

<?php

    namespace FarbenGesell\Configuration\Observer;

    use Magento\Framework\Event\ObserverInterface;
    use Magento\Framework\App\RequestInterface;

    class CustomPrice implements ObserverInterface
    {
        public function __construct(
    \Magento\Framework\App\RequestInterface $request
    )
    {
        $this->_request = $request;
    }

        public function execute(\Magento\Framework\Event\Observer $observer) {
            $item = $observer->getEvent()->getData('quote_item');         
            $item = ( $item->getParentItem() ? $item->getParentItem() : $item );

            $custom_price = $this->_request->getParam('custom_final_cal');

            $price = $custom_price;
            $item->setCustomPrice($price);
            $item->setOriginalCustomPrice($price);
            $item->getProduct()->setIsSuperMode(true);
        }

    }
?>
Was it helpful?

Solution

In your case, we need to pass your value to the request. The easiest way to this that we should add an hidden input to our form:

 <input type="hidden" name="custom_price" value="" id="custom_price_cal">

view/frontend/web/product.js

//Set the value to input
custom_price = price + product_attribute_value
$('#custom_price_cal').val(custom_price);

In your observer, we can the the param from request:

public function __construct(
    \Magento\Framework\App\RequestInterface $request
)
{
    $this->_request = $request;
}

 public function execute(\Magento\Framework\Event\Observer $observer) {
    $this->_request->getParam('custom_price');
    ......    
 }
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top