Magento 2 Add to cart frontend event listener
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}
I am trying to find good solution to execute custom javascript when product is successfully added to cart. Also this custom javascript need information about product that was added to cart (sku
, qty
, price
, name
, etc.)
Currently I come up with the following way to get information about products added to cart:
- Rewrite
$.mage.catalogAddToCart.prototype.enableAddToCartButton
(for products added to cart from catalog or product view page) - Rewrite
$.mage.dataPost.prototype.postData
(for products added to cart from widgets)
To get necessary information I have to parse page (f.e. to get qty
) and output additional infromation to page (f.e. to get sku
having product id
)
However my solution:
- has two entry points
- does not look nice
- does not handle situation when validation is failed on backend
- does not provide me all required information conveniently
Unfortunately I was not able to find any suitable extension point of checkout minicart to resolve my problem.
Any suggestions are much appreciated!
magento2 javascript addtocart mini-cart knockoutjs
bumped to the homepage by Community♦ 3 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
add a comment |
I am trying to find good solution to execute custom javascript when product is successfully added to cart. Also this custom javascript need information about product that was added to cart (sku
, qty
, price
, name
, etc.)
Currently I come up with the following way to get information about products added to cart:
- Rewrite
$.mage.catalogAddToCart.prototype.enableAddToCartButton
(for products added to cart from catalog or product view page) - Rewrite
$.mage.dataPost.prototype.postData
(for products added to cart from widgets)
To get necessary information I have to parse page (f.e. to get qty
) and output additional infromation to page (f.e. to get sku
having product id
)
However my solution:
- has two entry points
- does not look nice
- does not handle situation when validation is failed on backend
- does not provide me all required information conveniently
Unfortunately I was not able to find any suitable extension point of checkout minicart to resolve my problem.
Any suggestions are much appreciated!
magento2 javascript addtocart mini-cart knockoutjs
bumped to the homepage by Community♦ 3 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
I have a similar situation. I have reviewed Magento code and logic and does not find any solution. So, Magento does not support it and maybe, it makes sense because you can add product without Ajax request. But, I must have solution for my task and I wrote the following file (cart-update.js): require([ 'jquery', 'underscore', 'jquery/jquery-storageapi' ], function($, _) { var storage = $.initNamespaceStorage('mage-cache-storage').localStorage; $(document).on('ajaxComplete', function (event, xhr, settings) { if (settings.url.match(/customer/section/load/i) && xhr.responseJSON && xhr.responseJ
– Oleksiy
Aug 16 '17 at 20:54
Have you tried using mixins? alanstorm.com/the-curious-case-of-magento-2-mixins I personally use them often. Just like the php version of plugins. If you get stuck let me know and I can provide a solution.
– Chris Anderson
Jul 25 '18 at 17:21
@ChrisAnderson thanks, but actually my current ugly solution described in the question is implemented using mixins.
– Sergii Ivashchenko
Jul 27 '18 at 11:28
add a comment |
I am trying to find good solution to execute custom javascript when product is successfully added to cart. Also this custom javascript need information about product that was added to cart (sku
, qty
, price
, name
, etc.)
Currently I come up with the following way to get information about products added to cart:
- Rewrite
$.mage.catalogAddToCart.prototype.enableAddToCartButton
(for products added to cart from catalog or product view page) - Rewrite
$.mage.dataPost.prototype.postData
(for products added to cart from widgets)
To get necessary information I have to parse page (f.e. to get qty
) and output additional infromation to page (f.e. to get sku
having product id
)
However my solution:
- has two entry points
- does not look nice
- does not handle situation when validation is failed on backend
- does not provide me all required information conveniently
Unfortunately I was not able to find any suitable extension point of checkout minicart to resolve my problem.
Any suggestions are much appreciated!
magento2 javascript addtocart mini-cart knockoutjs
I am trying to find good solution to execute custom javascript when product is successfully added to cart. Also this custom javascript need information about product that was added to cart (sku
, qty
, price
, name
, etc.)
Currently I come up with the following way to get information about products added to cart:
- Rewrite
$.mage.catalogAddToCart.prototype.enableAddToCartButton
(for products added to cart from catalog or product view page) - Rewrite
$.mage.dataPost.prototype.postData
(for products added to cart from widgets)
To get necessary information I have to parse page (f.e. to get qty
) and output additional infromation to page (f.e. to get sku
having product id
)
However my solution:
- has two entry points
- does not look nice
- does not handle situation when validation is failed on backend
- does not provide me all required information conveniently
Unfortunately I was not able to find any suitable extension point of checkout minicart to resolve my problem.
Any suggestions are much appreciated!
magento2 javascript addtocart mini-cart knockoutjs
magento2 javascript addtocart mini-cart knockoutjs
edited Dec 5 '16 at 15:06
QuestionsQuestions
99112
99112
asked Mar 18 '16 at 10:31
Sergii IvashchenkoSergii Ivashchenko
884717
884717
bumped to the homepage by Community♦ 3 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
bumped to the homepage by Community♦ 3 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
I have a similar situation. I have reviewed Magento code and logic and does not find any solution. So, Magento does not support it and maybe, it makes sense because you can add product without Ajax request. But, I must have solution for my task and I wrote the following file (cart-update.js): require([ 'jquery', 'underscore', 'jquery/jquery-storageapi' ], function($, _) { var storage = $.initNamespaceStorage('mage-cache-storage').localStorage; $(document).on('ajaxComplete', function (event, xhr, settings) { if (settings.url.match(/customer/section/load/i) && xhr.responseJSON && xhr.responseJ
– Oleksiy
Aug 16 '17 at 20:54
Have you tried using mixins? alanstorm.com/the-curious-case-of-magento-2-mixins I personally use them often. Just like the php version of plugins. If you get stuck let me know and I can provide a solution.
– Chris Anderson
Jul 25 '18 at 17:21
@ChrisAnderson thanks, but actually my current ugly solution described in the question is implemented using mixins.
– Sergii Ivashchenko
Jul 27 '18 at 11:28
add a comment |
I have a similar situation. I have reviewed Magento code and logic and does not find any solution. So, Magento does not support it and maybe, it makes sense because you can add product without Ajax request. But, I must have solution for my task and I wrote the following file (cart-update.js): require([ 'jquery', 'underscore', 'jquery/jquery-storageapi' ], function($, _) { var storage = $.initNamespaceStorage('mage-cache-storage').localStorage; $(document).on('ajaxComplete', function (event, xhr, settings) { if (settings.url.match(/customer/section/load/i) && xhr.responseJSON && xhr.responseJ
– Oleksiy
Aug 16 '17 at 20:54
Have you tried using mixins? alanstorm.com/the-curious-case-of-magento-2-mixins I personally use them often. Just like the php version of plugins. If you get stuck let me know and I can provide a solution.
– Chris Anderson
Jul 25 '18 at 17:21
@ChrisAnderson thanks, but actually my current ugly solution described in the question is implemented using mixins.
– Sergii Ivashchenko
Jul 27 '18 at 11:28
I have a similar situation. I have reviewed Magento code and logic and does not find any solution. So, Magento does not support it and maybe, it makes sense because you can add product without Ajax request. But, I must have solution for my task and I wrote the following file (cart-update.js): require([ 'jquery', 'underscore', 'jquery/jquery-storageapi' ], function($, _) { var storage = $.initNamespaceStorage('mage-cache-storage').localStorage; $(document).on('ajaxComplete', function (event, xhr, settings) { if (settings.url.match(/customer/section/load/i) && xhr.responseJSON && xhr.responseJ
– Oleksiy
Aug 16 '17 at 20:54
I have a similar situation. I have reviewed Magento code and logic and does not find any solution. So, Magento does not support it and maybe, it makes sense because you can add product without Ajax request. But, I must have solution for my task and I wrote the following file (cart-update.js): require([ 'jquery', 'underscore', 'jquery/jquery-storageapi' ], function($, _) { var storage = $.initNamespaceStorage('mage-cache-storage').localStorage; $(document).on('ajaxComplete', function (event, xhr, settings) { if (settings.url.match(/customer/section/load/i) && xhr.responseJSON && xhr.responseJ
– Oleksiy
Aug 16 '17 at 20:54
Have you tried using mixins? alanstorm.com/the-curious-case-of-magento-2-mixins I personally use them often. Just like the php version of plugins. If you get stuck let me know and I can provide a solution.
– Chris Anderson
Jul 25 '18 at 17:21
Have you tried using mixins? alanstorm.com/the-curious-case-of-magento-2-mixins I personally use them often. Just like the php version of plugins. If you get stuck let me know and I can provide a solution.
– Chris Anderson
Jul 25 '18 at 17:21
@ChrisAnderson thanks, but actually my current ugly solution described in the question is implemented using mixins.
– Sergii Ivashchenko
Jul 27 '18 at 11:28
@ChrisAnderson thanks, but actually my current ugly solution described in the question is implemented using mixins.
– Sergii Ivashchenko
Jul 27 '18 at 11:28
add a comment |
1 Answer
1
active
oldest
votes
A solution is to write a mixin for the catalogAddToCart ajaxSubmit function. Usually the data you require would not be available here but this can be fixed by modifying the checkout/cart/add controller to return the data. Full solution below, currently it just javascript alerts the data you needed on add to cart success.
app/code/VendorName/ModuleName/registration.php
<?php
MagentoFrameworkComponentComponentRegistrar::register(
MagentoFrameworkComponentComponentRegistrar::MODULE,
'VendorName_ModuleName',
__DIR__
);
app/code/VendorName/ModuleName/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="VendorName_ModuleName" setup_version="1.0.0">
<sequence>
<module name="Magento_Catalog"/>
<module name="Magento_Checkout"/>
</sequence>
</module>
</config>
app/code/VendorName/ModuleName/etc/frontend/di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="MagentoCheckoutControllerCartAdd" type="VendorNameModuleNameControllerCartAdd"/>
</config>
app/code/VendorName/ModuleName/Controller/Cart/Add.php
<?php
namespace VendorNameModuleNameControllerCart;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Add extends MagentoCheckoutControllerCartAdd
{
/**
* Add product to shopping cart action
*
* @return MagentoFrameworkControllerResultRedirect
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function execute()
{
if (!$this->_formKeyValidator->validate($this->getRequest())) {
return $this->resultRedirectFactory->create()->setPath('*/*/');
}
$params = $this->getRequest()->getParams();
try {
if (isset($params['qty'])) {
$filter = new Zend_Filter_LocalizedToNormalized(
['locale' => $this->_objectManager->get(
MagentoFrameworkLocaleResolverInterface::class
)->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 MagentoWishlistObserverAddToCart
*/
$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, [
'sku' => $product->getSku(),
'name' => $product->getName(),
'price' => $product->getPrice(),
'qty' => isset($params['qty'])?$params['qty']:null
]);
}
} catch (MagentoFrameworkExceptionLocalizedException $e) {
if ($this->_checkoutSession->getUseNotice(true)) {
$this->messageManager->addNotice(
$this->_objectManager->get(MagentoFrameworkEscaper::class)->escapeHtml($e->getMessage())
);
} else {
$messages = array_unique(explode("n", $e->getMessage()));
foreach ($messages as $message) {
$this->messageManager->addError(
$this->_objectManager->get(MagentoFrameworkEscaper::class)->escapeHtml($message)
);
}
}
$url = $this->_checkoutSession->getRedirectUrl(true);
if (!$url) {
$cartUrl = $this->_objectManager->get(MagentoCheckoutHelperCart::class)->getCartUrl();
$url = $this->_redirect->getRedirectUrl($cartUrl);
}
return $this->goBack($url);
} catch (Exception $e) {
$this->messageManager->addException($e, __('We can't add this item to your shopping cart right now.'));
$this->_objectManager->get(PsrLogLoggerInterface::class)->critical($e);
return $this->goBack();
}
}
/**
* Resolve response
*
* @param string $backUrl
* @param MagentoCatalogModelProduct $product
* @return $this|MagentoFrameworkControllerResultRedirect
*/
protected function goBack($backUrl = null, $product = null, $result = )
{
if (!$this->getRequest()->isAjax()) {
return parent::_goBack($backUrl);
}
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(MagentoFrameworkJsonHelperData::class)->jsonEncode($result)
);
}
}
app/code/VendorName/ModuleName/view/frontend/requirejs-config.js
var config = {
config: {
mixins: {
'Magento_Catalog/js/catalog-add-to-cart': {
'VendorName_ModuleName/js/catalog-add-to-cart-mixin': true
},
}
}
};
app/code/VendorName/ModuleName/view/frontend/web/js/catalog-add-to-cart-mixin.js
define([
'jquery',
], function ($) {
'use strict';
return function (widget) {
$.widget('mage.catalogAddToCart', widget, {
/**
* @param {String} form
*/
ajaxSubmit: function (form) {
var self = this;
$(self.options.minicartSelector).trigger('contentLoading');
self.disableAddToCartButton(form);
$.ajax({
url: form.attr('action'),
data: form.serialize(),
type: 'post',
dataType: 'json',
/** @inheritdoc */
beforeSend: function () {
if (self.isLoaderEnabled()) {
$('body').trigger(self.options.processStart);
}
},
/** @inheritdoc */
success: function (res) {
alert(JSON.stringify(res));
var eventData, parameters;
$(document).trigger('ajax:addToCart', form.data().productSku);
if (self.isLoaderEnabled()) {
$('body').trigger(self.options.processStop);
}
if (res.backUrl) {
eventData = {
'form': form,
'redirectParameters':
};
// trigger global event, so other modules will be able add parameters to redirect url
$('body').trigger('catalogCategoryAddToCartRedirect', eventData);
if (eventData.redirectParameters.length > 0) {
parameters = res.backUrl.split('#');
parameters.push(eventData.redirectParameters.join('&'));
res.backUrl = parameters.join('#');
}
window.location = res.backUrl;
return;
}
if (res.messages) {
$(self.options.messagesSelector).html(res.messages);
}
if (res.minicart) {
$(self.options.minicartSelector).replaceWith(res.minicart);
$(self.options.minicartSelector).trigger('contentUpdated');
}
if (res.product && res.product.statusText) {
$(self.options.productStatusSelector)
.removeClass('available')
.addClass('unavailable')
.find('span')
.html(res.product.statusText);
}
self.enableAddToCartButton(form);
}
});
}
});
return $.mage.catalogAddToCart;
}
});
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "479"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmagento.stackexchange.com%2fquestions%2f106878%2fmagento-2-add-to-cart-frontend-event-listener%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
A solution is to write a mixin for the catalogAddToCart ajaxSubmit function. Usually the data you require would not be available here but this can be fixed by modifying the checkout/cart/add controller to return the data. Full solution below, currently it just javascript alerts the data you needed on add to cart success.
app/code/VendorName/ModuleName/registration.php
<?php
MagentoFrameworkComponentComponentRegistrar::register(
MagentoFrameworkComponentComponentRegistrar::MODULE,
'VendorName_ModuleName',
__DIR__
);
app/code/VendorName/ModuleName/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="VendorName_ModuleName" setup_version="1.0.0">
<sequence>
<module name="Magento_Catalog"/>
<module name="Magento_Checkout"/>
</sequence>
</module>
</config>
app/code/VendorName/ModuleName/etc/frontend/di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="MagentoCheckoutControllerCartAdd" type="VendorNameModuleNameControllerCartAdd"/>
</config>
app/code/VendorName/ModuleName/Controller/Cart/Add.php
<?php
namespace VendorNameModuleNameControllerCart;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Add extends MagentoCheckoutControllerCartAdd
{
/**
* Add product to shopping cart action
*
* @return MagentoFrameworkControllerResultRedirect
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function execute()
{
if (!$this->_formKeyValidator->validate($this->getRequest())) {
return $this->resultRedirectFactory->create()->setPath('*/*/');
}
$params = $this->getRequest()->getParams();
try {
if (isset($params['qty'])) {
$filter = new Zend_Filter_LocalizedToNormalized(
['locale' => $this->_objectManager->get(
MagentoFrameworkLocaleResolverInterface::class
)->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 MagentoWishlistObserverAddToCart
*/
$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, [
'sku' => $product->getSku(),
'name' => $product->getName(),
'price' => $product->getPrice(),
'qty' => isset($params['qty'])?$params['qty']:null
]);
}
} catch (MagentoFrameworkExceptionLocalizedException $e) {
if ($this->_checkoutSession->getUseNotice(true)) {
$this->messageManager->addNotice(
$this->_objectManager->get(MagentoFrameworkEscaper::class)->escapeHtml($e->getMessage())
);
} else {
$messages = array_unique(explode("n", $e->getMessage()));
foreach ($messages as $message) {
$this->messageManager->addError(
$this->_objectManager->get(MagentoFrameworkEscaper::class)->escapeHtml($message)
);
}
}
$url = $this->_checkoutSession->getRedirectUrl(true);
if (!$url) {
$cartUrl = $this->_objectManager->get(MagentoCheckoutHelperCart::class)->getCartUrl();
$url = $this->_redirect->getRedirectUrl($cartUrl);
}
return $this->goBack($url);
} catch (Exception $e) {
$this->messageManager->addException($e, __('We can't add this item to your shopping cart right now.'));
$this->_objectManager->get(PsrLogLoggerInterface::class)->critical($e);
return $this->goBack();
}
}
/**
* Resolve response
*
* @param string $backUrl
* @param MagentoCatalogModelProduct $product
* @return $this|MagentoFrameworkControllerResultRedirect
*/
protected function goBack($backUrl = null, $product = null, $result = )
{
if (!$this->getRequest()->isAjax()) {
return parent::_goBack($backUrl);
}
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(MagentoFrameworkJsonHelperData::class)->jsonEncode($result)
);
}
}
app/code/VendorName/ModuleName/view/frontend/requirejs-config.js
var config = {
config: {
mixins: {
'Magento_Catalog/js/catalog-add-to-cart': {
'VendorName_ModuleName/js/catalog-add-to-cart-mixin': true
},
}
}
};
app/code/VendorName/ModuleName/view/frontend/web/js/catalog-add-to-cart-mixin.js
define([
'jquery',
], function ($) {
'use strict';
return function (widget) {
$.widget('mage.catalogAddToCart', widget, {
/**
* @param {String} form
*/
ajaxSubmit: function (form) {
var self = this;
$(self.options.minicartSelector).trigger('contentLoading');
self.disableAddToCartButton(form);
$.ajax({
url: form.attr('action'),
data: form.serialize(),
type: 'post',
dataType: 'json',
/** @inheritdoc */
beforeSend: function () {
if (self.isLoaderEnabled()) {
$('body').trigger(self.options.processStart);
}
},
/** @inheritdoc */
success: function (res) {
alert(JSON.stringify(res));
var eventData, parameters;
$(document).trigger('ajax:addToCart', form.data().productSku);
if (self.isLoaderEnabled()) {
$('body').trigger(self.options.processStop);
}
if (res.backUrl) {
eventData = {
'form': form,
'redirectParameters':
};
// trigger global event, so other modules will be able add parameters to redirect url
$('body').trigger('catalogCategoryAddToCartRedirect', eventData);
if (eventData.redirectParameters.length > 0) {
parameters = res.backUrl.split('#');
parameters.push(eventData.redirectParameters.join('&'));
res.backUrl = parameters.join('#');
}
window.location = res.backUrl;
return;
}
if (res.messages) {
$(self.options.messagesSelector).html(res.messages);
}
if (res.minicart) {
$(self.options.minicartSelector).replaceWith(res.minicart);
$(self.options.minicartSelector).trigger('contentUpdated');
}
if (res.product && res.product.statusText) {
$(self.options.productStatusSelector)
.removeClass('available')
.addClass('unavailable')
.find('span')
.html(res.product.statusText);
}
self.enableAddToCartButton(form);
}
});
}
});
return $.mage.catalogAddToCart;
}
});
add a comment |
A solution is to write a mixin for the catalogAddToCart ajaxSubmit function. Usually the data you require would not be available here but this can be fixed by modifying the checkout/cart/add controller to return the data. Full solution below, currently it just javascript alerts the data you needed on add to cart success.
app/code/VendorName/ModuleName/registration.php
<?php
MagentoFrameworkComponentComponentRegistrar::register(
MagentoFrameworkComponentComponentRegistrar::MODULE,
'VendorName_ModuleName',
__DIR__
);
app/code/VendorName/ModuleName/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="VendorName_ModuleName" setup_version="1.0.0">
<sequence>
<module name="Magento_Catalog"/>
<module name="Magento_Checkout"/>
</sequence>
</module>
</config>
app/code/VendorName/ModuleName/etc/frontend/di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="MagentoCheckoutControllerCartAdd" type="VendorNameModuleNameControllerCartAdd"/>
</config>
app/code/VendorName/ModuleName/Controller/Cart/Add.php
<?php
namespace VendorNameModuleNameControllerCart;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Add extends MagentoCheckoutControllerCartAdd
{
/**
* Add product to shopping cart action
*
* @return MagentoFrameworkControllerResultRedirect
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function execute()
{
if (!$this->_formKeyValidator->validate($this->getRequest())) {
return $this->resultRedirectFactory->create()->setPath('*/*/');
}
$params = $this->getRequest()->getParams();
try {
if (isset($params['qty'])) {
$filter = new Zend_Filter_LocalizedToNormalized(
['locale' => $this->_objectManager->get(
MagentoFrameworkLocaleResolverInterface::class
)->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 MagentoWishlistObserverAddToCart
*/
$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, [
'sku' => $product->getSku(),
'name' => $product->getName(),
'price' => $product->getPrice(),
'qty' => isset($params['qty'])?$params['qty']:null
]);
}
} catch (MagentoFrameworkExceptionLocalizedException $e) {
if ($this->_checkoutSession->getUseNotice(true)) {
$this->messageManager->addNotice(
$this->_objectManager->get(MagentoFrameworkEscaper::class)->escapeHtml($e->getMessage())
);
} else {
$messages = array_unique(explode("n", $e->getMessage()));
foreach ($messages as $message) {
$this->messageManager->addError(
$this->_objectManager->get(MagentoFrameworkEscaper::class)->escapeHtml($message)
);
}
}
$url = $this->_checkoutSession->getRedirectUrl(true);
if (!$url) {
$cartUrl = $this->_objectManager->get(MagentoCheckoutHelperCart::class)->getCartUrl();
$url = $this->_redirect->getRedirectUrl($cartUrl);
}
return $this->goBack($url);
} catch (Exception $e) {
$this->messageManager->addException($e, __('We can't add this item to your shopping cart right now.'));
$this->_objectManager->get(PsrLogLoggerInterface::class)->critical($e);
return $this->goBack();
}
}
/**
* Resolve response
*
* @param string $backUrl
* @param MagentoCatalogModelProduct $product
* @return $this|MagentoFrameworkControllerResultRedirect
*/
protected function goBack($backUrl = null, $product = null, $result = )
{
if (!$this->getRequest()->isAjax()) {
return parent::_goBack($backUrl);
}
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(MagentoFrameworkJsonHelperData::class)->jsonEncode($result)
);
}
}
app/code/VendorName/ModuleName/view/frontend/requirejs-config.js
var config = {
config: {
mixins: {
'Magento_Catalog/js/catalog-add-to-cart': {
'VendorName_ModuleName/js/catalog-add-to-cart-mixin': true
},
}
}
};
app/code/VendorName/ModuleName/view/frontend/web/js/catalog-add-to-cart-mixin.js
define([
'jquery',
], function ($) {
'use strict';
return function (widget) {
$.widget('mage.catalogAddToCart', widget, {
/**
* @param {String} form
*/
ajaxSubmit: function (form) {
var self = this;
$(self.options.minicartSelector).trigger('contentLoading');
self.disableAddToCartButton(form);
$.ajax({
url: form.attr('action'),
data: form.serialize(),
type: 'post',
dataType: 'json',
/** @inheritdoc */
beforeSend: function () {
if (self.isLoaderEnabled()) {
$('body').trigger(self.options.processStart);
}
},
/** @inheritdoc */
success: function (res) {
alert(JSON.stringify(res));
var eventData, parameters;
$(document).trigger('ajax:addToCart', form.data().productSku);
if (self.isLoaderEnabled()) {
$('body').trigger(self.options.processStop);
}
if (res.backUrl) {
eventData = {
'form': form,
'redirectParameters':
};
// trigger global event, so other modules will be able add parameters to redirect url
$('body').trigger('catalogCategoryAddToCartRedirect', eventData);
if (eventData.redirectParameters.length > 0) {
parameters = res.backUrl.split('#');
parameters.push(eventData.redirectParameters.join('&'));
res.backUrl = parameters.join('#');
}
window.location = res.backUrl;
return;
}
if (res.messages) {
$(self.options.messagesSelector).html(res.messages);
}
if (res.minicart) {
$(self.options.minicartSelector).replaceWith(res.minicart);
$(self.options.minicartSelector).trigger('contentUpdated');
}
if (res.product && res.product.statusText) {
$(self.options.productStatusSelector)
.removeClass('available')
.addClass('unavailable')
.find('span')
.html(res.product.statusText);
}
self.enableAddToCartButton(form);
}
});
}
});
return $.mage.catalogAddToCart;
}
});
add a comment |
A solution is to write a mixin for the catalogAddToCart ajaxSubmit function. Usually the data you require would not be available here but this can be fixed by modifying the checkout/cart/add controller to return the data. Full solution below, currently it just javascript alerts the data you needed on add to cart success.
app/code/VendorName/ModuleName/registration.php
<?php
MagentoFrameworkComponentComponentRegistrar::register(
MagentoFrameworkComponentComponentRegistrar::MODULE,
'VendorName_ModuleName',
__DIR__
);
app/code/VendorName/ModuleName/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="VendorName_ModuleName" setup_version="1.0.0">
<sequence>
<module name="Magento_Catalog"/>
<module name="Magento_Checkout"/>
</sequence>
</module>
</config>
app/code/VendorName/ModuleName/etc/frontend/di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="MagentoCheckoutControllerCartAdd" type="VendorNameModuleNameControllerCartAdd"/>
</config>
app/code/VendorName/ModuleName/Controller/Cart/Add.php
<?php
namespace VendorNameModuleNameControllerCart;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Add extends MagentoCheckoutControllerCartAdd
{
/**
* Add product to shopping cart action
*
* @return MagentoFrameworkControllerResultRedirect
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function execute()
{
if (!$this->_formKeyValidator->validate($this->getRequest())) {
return $this->resultRedirectFactory->create()->setPath('*/*/');
}
$params = $this->getRequest()->getParams();
try {
if (isset($params['qty'])) {
$filter = new Zend_Filter_LocalizedToNormalized(
['locale' => $this->_objectManager->get(
MagentoFrameworkLocaleResolverInterface::class
)->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 MagentoWishlistObserverAddToCart
*/
$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, [
'sku' => $product->getSku(),
'name' => $product->getName(),
'price' => $product->getPrice(),
'qty' => isset($params['qty'])?$params['qty']:null
]);
}
} catch (MagentoFrameworkExceptionLocalizedException $e) {
if ($this->_checkoutSession->getUseNotice(true)) {
$this->messageManager->addNotice(
$this->_objectManager->get(MagentoFrameworkEscaper::class)->escapeHtml($e->getMessage())
);
} else {
$messages = array_unique(explode("n", $e->getMessage()));
foreach ($messages as $message) {
$this->messageManager->addError(
$this->_objectManager->get(MagentoFrameworkEscaper::class)->escapeHtml($message)
);
}
}
$url = $this->_checkoutSession->getRedirectUrl(true);
if (!$url) {
$cartUrl = $this->_objectManager->get(MagentoCheckoutHelperCart::class)->getCartUrl();
$url = $this->_redirect->getRedirectUrl($cartUrl);
}
return $this->goBack($url);
} catch (Exception $e) {
$this->messageManager->addException($e, __('We can't add this item to your shopping cart right now.'));
$this->_objectManager->get(PsrLogLoggerInterface::class)->critical($e);
return $this->goBack();
}
}
/**
* Resolve response
*
* @param string $backUrl
* @param MagentoCatalogModelProduct $product
* @return $this|MagentoFrameworkControllerResultRedirect
*/
protected function goBack($backUrl = null, $product = null, $result = )
{
if (!$this->getRequest()->isAjax()) {
return parent::_goBack($backUrl);
}
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(MagentoFrameworkJsonHelperData::class)->jsonEncode($result)
);
}
}
app/code/VendorName/ModuleName/view/frontend/requirejs-config.js
var config = {
config: {
mixins: {
'Magento_Catalog/js/catalog-add-to-cart': {
'VendorName_ModuleName/js/catalog-add-to-cart-mixin': true
},
}
}
};
app/code/VendorName/ModuleName/view/frontend/web/js/catalog-add-to-cart-mixin.js
define([
'jquery',
], function ($) {
'use strict';
return function (widget) {
$.widget('mage.catalogAddToCart', widget, {
/**
* @param {String} form
*/
ajaxSubmit: function (form) {
var self = this;
$(self.options.minicartSelector).trigger('contentLoading');
self.disableAddToCartButton(form);
$.ajax({
url: form.attr('action'),
data: form.serialize(),
type: 'post',
dataType: 'json',
/** @inheritdoc */
beforeSend: function () {
if (self.isLoaderEnabled()) {
$('body').trigger(self.options.processStart);
}
},
/** @inheritdoc */
success: function (res) {
alert(JSON.stringify(res));
var eventData, parameters;
$(document).trigger('ajax:addToCart', form.data().productSku);
if (self.isLoaderEnabled()) {
$('body').trigger(self.options.processStop);
}
if (res.backUrl) {
eventData = {
'form': form,
'redirectParameters':
};
// trigger global event, so other modules will be able add parameters to redirect url
$('body').trigger('catalogCategoryAddToCartRedirect', eventData);
if (eventData.redirectParameters.length > 0) {
parameters = res.backUrl.split('#');
parameters.push(eventData.redirectParameters.join('&'));
res.backUrl = parameters.join('#');
}
window.location = res.backUrl;
return;
}
if (res.messages) {
$(self.options.messagesSelector).html(res.messages);
}
if (res.minicart) {
$(self.options.minicartSelector).replaceWith(res.minicart);
$(self.options.minicartSelector).trigger('contentUpdated');
}
if (res.product && res.product.statusText) {
$(self.options.productStatusSelector)
.removeClass('available')
.addClass('unavailable')
.find('span')
.html(res.product.statusText);
}
self.enableAddToCartButton(form);
}
});
}
});
return $.mage.catalogAddToCart;
}
});
A solution is to write a mixin for the catalogAddToCart ajaxSubmit function. Usually the data you require would not be available here but this can be fixed by modifying the checkout/cart/add controller to return the data. Full solution below, currently it just javascript alerts the data you needed on add to cart success.
app/code/VendorName/ModuleName/registration.php
<?php
MagentoFrameworkComponentComponentRegistrar::register(
MagentoFrameworkComponentComponentRegistrar::MODULE,
'VendorName_ModuleName',
__DIR__
);
app/code/VendorName/ModuleName/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="VendorName_ModuleName" setup_version="1.0.0">
<sequence>
<module name="Magento_Catalog"/>
<module name="Magento_Checkout"/>
</sequence>
</module>
</config>
app/code/VendorName/ModuleName/etc/frontend/di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="MagentoCheckoutControllerCartAdd" type="VendorNameModuleNameControllerCartAdd"/>
</config>
app/code/VendorName/ModuleName/Controller/Cart/Add.php
<?php
namespace VendorNameModuleNameControllerCart;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Add extends MagentoCheckoutControllerCartAdd
{
/**
* Add product to shopping cart action
*
* @return MagentoFrameworkControllerResultRedirect
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function execute()
{
if (!$this->_formKeyValidator->validate($this->getRequest())) {
return $this->resultRedirectFactory->create()->setPath('*/*/');
}
$params = $this->getRequest()->getParams();
try {
if (isset($params['qty'])) {
$filter = new Zend_Filter_LocalizedToNormalized(
['locale' => $this->_objectManager->get(
MagentoFrameworkLocaleResolverInterface::class
)->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 MagentoWishlistObserverAddToCart
*/
$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, [
'sku' => $product->getSku(),
'name' => $product->getName(),
'price' => $product->getPrice(),
'qty' => isset($params['qty'])?$params['qty']:null
]);
}
} catch (MagentoFrameworkExceptionLocalizedException $e) {
if ($this->_checkoutSession->getUseNotice(true)) {
$this->messageManager->addNotice(
$this->_objectManager->get(MagentoFrameworkEscaper::class)->escapeHtml($e->getMessage())
);
} else {
$messages = array_unique(explode("n", $e->getMessage()));
foreach ($messages as $message) {
$this->messageManager->addError(
$this->_objectManager->get(MagentoFrameworkEscaper::class)->escapeHtml($message)
);
}
}
$url = $this->_checkoutSession->getRedirectUrl(true);
if (!$url) {
$cartUrl = $this->_objectManager->get(MagentoCheckoutHelperCart::class)->getCartUrl();
$url = $this->_redirect->getRedirectUrl($cartUrl);
}
return $this->goBack($url);
} catch (Exception $e) {
$this->messageManager->addException($e, __('We can't add this item to your shopping cart right now.'));
$this->_objectManager->get(PsrLogLoggerInterface::class)->critical($e);
return $this->goBack();
}
}
/**
* Resolve response
*
* @param string $backUrl
* @param MagentoCatalogModelProduct $product
* @return $this|MagentoFrameworkControllerResultRedirect
*/
protected function goBack($backUrl = null, $product = null, $result = )
{
if (!$this->getRequest()->isAjax()) {
return parent::_goBack($backUrl);
}
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(MagentoFrameworkJsonHelperData::class)->jsonEncode($result)
);
}
}
app/code/VendorName/ModuleName/view/frontend/requirejs-config.js
var config = {
config: {
mixins: {
'Magento_Catalog/js/catalog-add-to-cart': {
'VendorName_ModuleName/js/catalog-add-to-cart-mixin': true
},
}
}
};
app/code/VendorName/ModuleName/view/frontend/web/js/catalog-add-to-cart-mixin.js
define([
'jquery',
], function ($) {
'use strict';
return function (widget) {
$.widget('mage.catalogAddToCart', widget, {
/**
* @param {String} form
*/
ajaxSubmit: function (form) {
var self = this;
$(self.options.minicartSelector).trigger('contentLoading');
self.disableAddToCartButton(form);
$.ajax({
url: form.attr('action'),
data: form.serialize(),
type: 'post',
dataType: 'json',
/** @inheritdoc */
beforeSend: function () {
if (self.isLoaderEnabled()) {
$('body').trigger(self.options.processStart);
}
},
/** @inheritdoc */
success: function (res) {
alert(JSON.stringify(res));
var eventData, parameters;
$(document).trigger('ajax:addToCart', form.data().productSku);
if (self.isLoaderEnabled()) {
$('body').trigger(self.options.processStop);
}
if (res.backUrl) {
eventData = {
'form': form,
'redirectParameters':
};
// trigger global event, so other modules will be able add parameters to redirect url
$('body').trigger('catalogCategoryAddToCartRedirect', eventData);
if (eventData.redirectParameters.length > 0) {
parameters = res.backUrl.split('#');
parameters.push(eventData.redirectParameters.join('&'));
res.backUrl = parameters.join('#');
}
window.location = res.backUrl;
return;
}
if (res.messages) {
$(self.options.messagesSelector).html(res.messages);
}
if (res.minicart) {
$(self.options.minicartSelector).replaceWith(res.minicart);
$(self.options.minicartSelector).trigger('contentUpdated');
}
if (res.product && res.product.statusText) {
$(self.options.productStatusSelector)
.removeClass('available')
.addClass('unavailable')
.find('span')
.html(res.product.statusText);
}
self.enableAddToCartButton(form);
}
});
}
});
return $.mage.catalogAddToCart;
}
});
answered Aug 24 '18 at 13:30
Media LoungeMedia Lounge
1565
1565
add a comment |
add a comment |
Thanks for contributing an answer to Magento Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmagento.stackexchange.com%2fquestions%2f106878%2fmagento-2-add-to-cart-frontend-event-listener%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I have a similar situation. I have reviewed Magento code and logic and does not find any solution. So, Magento does not support it and maybe, it makes sense because you can add product without Ajax request. But, I must have solution for my task and I wrote the following file (cart-update.js): require([ 'jquery', 'underscore', 'jquery/jquery-storageapi' ], function($, _) { var storage = $.initNamespaceStorage('mage-cache-storage').localStorage; $(document).on('ajaxComplete', function (event, xhr, settings) { if (settings.url.match(/customer/section/load/i) && xhr.responseJSON && xhr.responseJ
– Oleksiy
Aug 16 '17 at 20:54
Have you tried using mixins? alanstorm.com/the-curious-case-of-magento-2-mixins I personally use them often. Just like the php version of plugins. If you get stuck let me know and I can provide a solution.
– Chris Anderson
Jul 25 '18 at 17:21
@ChrisAnderson thanks, but actually my current ugly solution described in the question is implemented using mixins.
– Sergii Ivashchenko
Jul 27 '18 at 11:28