I want to display a custom message on product page after Ajax add to cart success message in list page. Can you suggest anyway?
Magento – How to display custom message
ajaxaddtocartmagento2.2success-message
Related Solutions
I have just finished a module for adding compare products via Ajax. The logic of module just followed the Magento core logic:
- Controller logic:
vendor/magento/module-catalog/Controller/Product/Compare/Add.php
- Javacript logic:
vendor/magento/module-catalog/view/frontend/web/js/catalog-add-to-cart.js
1) Declare our route.xml
app/code/Vendor/CatalogProduct/etc/frontend/routes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route id="catalog_product" frontName="catalog_product">
<module name="Vendor_CatalogProduct" />
</route>
</router>
</config>
2) We need to override the Block: \Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare
, because we need to build the Ajax url for each product. And, after adding product successfully, we need to reload compare product data (stored in browser storage).
app/code/Vendor/CatalogProduct/etc/frontend/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare" type="Vendor\CatalogProduct\Block\ProductList\Item\AddTo\Compare"/>
</config>
app/code/Vendor/CatalogProduct/etc/frontend/sections.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd">
<action name="catalog_product/compare/ajaxAdd">
<section name="compare-products"/>
</action>
</config>
3) Before building the Ajax controller logic and Js script, we need to custom the compare product layout.
app/code/Vendor/CatalogProduct/view/frontend/layout/catalog_category_view.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<referenceBlock name="category.product.addto.compare">
<action method="setTemplate">
<argument name="template" xsi:type="string">Vendor_CatalogProduct::compare/list/addto/compare.phtml</argument>
</action>
</referenceBlock>
<block class="Vendor\CatalogProduct\Block\Compare\Js" template="Vendor_CatalogProduct::compare/list/js.phtml" name="js.compare" after="-"/>
</referenceContainer>
</body>
</page>
Change the link to form data:
app/code/Vendor/CatalogProduct/view/frontend/templates/compare/list/addto/compare.phtml
<?php
// @codingStandardsIgnoreFile
/** @var $block \Vendor\CatalogProduct\Block\ProductList\Item\AddTo\Compare */
?>
<form data-role="addto-compare-form" action="<?php /* @escapeNotVerified */ echo $block->getAddToCompareAjaxUrl($this->getProduct())?>" method="post">
<?php echo $block->getBlockHtml('formkey')?>
<button type="submit" role="button"
title="<?php echo $block->escapeHtml(__('Add to Compare')); ?>"
class="action addtocompare primary">
<span><?php /* @escapeNotVerified */ echo __('Add to Compare') ?></span>
</button>
</form>
Need to add the Js script to template:
app/code/Vendor/CatalogProduct/view/frontend/templates/compare/list/js.phtml
<script type="text/x-magento-init">
{
"[data-role=addto-compare-form]": {
"Vendor_CatalogProduct/js/add-to-compare": {}
}
}
</script>
Blocks:
Vendor\CatalogProduct\Block\Compare\Js
should extend from \Magento\Framework\View\Element\Template
.
Vendor\CatalogProduct\Block\ProductList\Item\AddTo\Compare
will extend from Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare
.
public function getAddToCompareAjaxUrl($product)
{
$productId = $product->getId();
return $this->getUrl('catalog_product/compare/ajaxAdd', ['product' => $productId]);
}
4) Js script and Ajax controller Logic: followed the Magento core logic.
app/code/Vendor/CatalogProduct/view/frontend/web/js/add-to-compare.js
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
define([
'jquery',
'mage/translate',
'jquery/ui'
], function($, $t) {
"use strict";
$.widget('mage.catalogAddToCompare', {
options: {
processStart: null,
processStop: null,
bindSubmit: true,
messagesSelector: '[data-placeholder="messages"]'
},
_create: function() {
if (this.options.bindSubmit) {
this._bindSubmit();
}
},
_bindSubmit: function() {
var self = this;
this.element.on('submit', function(e) {
e.preventDefault();
self.submitForm($(this));
});
},
isLoaderEnabled: function() {
return this.options.processStart && this.options.processStop;
},
/**
* Handler for the form 'submit' event
*
* @param {Object} form
*/
submitForm: function (form) {
var self = this;
self.ajaxSubmit(form);
},
ajaxSubmit: function(form) {
var self = this;
$.ajax({
url: form.attr('action'),
data: form.serialize(),
type: 'post',
dataType: 'json',
beforeSend: function() {
if (self.isLoaderEnabled()) {
$('body').trigger(self.options.processStart);
}
},
success: function(res) {
if (self.isLoaderEnabled()) {
$('body').trigger(self.options.processStop);
}
if (res.backUrl) {
window.location = res.backUrl;
return;
}
if (res.messages) {
//$(self.options.messagesSelector).html(res.messages);
}
}
});
}
});
return $.mage.catalogAddToCompare;
});
app/code/Vendor/CatalogProduct/Controller/Compare/AjaxAdd.php
<?php
namespace Vendor\CatalogProduct\Controller\Compare;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Json\Helper\Data;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Customer\Model\Session as CustomerSession;
use Psr\Log\LoggerInterface;
use Magento\Framework\Data\Form\FormKey\Validator;
use Magento\Customer\Model\Visitor;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Catalog\Model\Product\Compare\ListCompare;
class AjaxAdd extends Action
{
/**
* @var CustomerSession
*/
protected $customerSession;
/**
* @var Visitor
*/
protected $customerVisitor;
/**
* @var ProductRepositoryInterface
*/
protected $productRepository;
/**
* @var StoreManagerInterface
*/
protected $storeManager;
protected $catalogProductCompareList;
/**
* @var Validator
*/
protected $formKeyValidator;
/**
* @var JsonFactory
*/
protected $jsonFactory;
/**
* @var Data
*/
protected $jsonHelper;
/**
* @var LoggerInterface
*/
protected $logger;
/**
* AjaxAdd constructor.
*
* @param Context $context
* @param CustomerSession $customerSession
* @param JsonFactory $jsonFactory
* @param Data $jsonHelper
* @param Visitor $visitor
* @param Validator $validator
* @param ProductRepositoryInterface $productRepository
* @param StoreManagerInterface $storeManager
* @param ListCompare $listCompare
* @param LoggerInterface $logger
*/
public function __construct(
Context $context,
CustomerSession $customerSession,
JsonFactory $jsonFactory,
Data $jsonHelper,
Visitor $visitor,
Validator $validator,
ProductRepositoryInterface $productRepository,
StoreManagerInterface $storeManager,
ListCompare $listCompare,
LoggerInterface $logger
) {
$this->customerSession = $customerSession;
$this->jsonFactory = $jsonFactory;
$this->jsonHelper = $jsonHelper;
$this->customerVisitor = $visitor;
$this->formKeyValidator = $validator;
$this->productRepository = $productRepository;
$this->storeManager = $storeManager;
$this->catalogProductCompareList = $listCompare;
$this->logger = $logger;
parent::__construct($context);
}
/**
* Ajax execute
*
*/
public function execute()
{
$response = [
'errors' => false
];
if ($this->getRequest()->isAjax()) {
if (!$this->formKeyValidator->validate($this->getRequest())) {
/** @var \Magento\Framework\Controller\Result\Raw $resultRaw */
$this->messageManager->addErrorMessage(__('Invalid form key.'));
$response = [
'errors' => true,
'messages' => __('Invalid form key.')
];
$resultJson = $this->jsonFactory->create();
return $resultJson->setData($response);
}
try {
$productId = (int)$this->getRequest()->getParam('product');
if ($productId && ($this->customerVisitor->getId() || $this->customerSession->isLoggedIn())) {
$storeId = $this->storeManager->getStore()->getId();
try {
$product = $this->productRepository->getById($productId, false, $storeId);
} catch (NoSuchEntityException $e) {
$product = null;
}
if ($product) {
$this->catalogProductCompareList->addProduct($product);
$productName = $this->_objectManager->get('Magento\Framework\Escaper')->escapeHtml($product->getName());
$response['messages'] = __('You added product %1 to the comparison list.', $productName);
$this->messageManager->addSuccessMessage(__('You added product %1 to the comparison list.', $productName));
$this->_eventManager->dispatch('catalog_product_compare_add_product', ['product' => $product]);
}
$this->_objectManager->get('Magento\Catalog\Helper\Product\Compare')->calculate();
}
} catch (\Exception $e) {
$response = [
'errors' => true,
'messages' => __('Some thing went wrong.')
];
$this->messageManager->addExceptionMessage($e, __('Some thing went wrong.'));
$this->logger->critical($e);
}
} else {
$response = [
'errors' => true,
'messages' => __('Need to access via Ajax.')
];
$this->messageManager->addErrorMessage(__('Need to access via Ajax.'));
}
/** @var \Magento\Framework\Controller\Result\Raw $resultRaw */
$resultJson = $this->jsonFactory->create();
return $resultJson->setData($response);
}
}
Remember to define registration.php
and module.xml
.
Now, on the product listing page, we can use Ajax for compare product function. However, this module only works on Product listing page, we need to improve it, it should work on Product detail page.
Submit the form via ajax
Use this script in your phtml:
<script type="text/javascript">
function callAjax(){
jQuery.ajax({
type : "POST",
url : "<?php echo Mage::getUrl('module/ctrlr/action'); ?>",
data : jQuery('#test_sample_form').serialize(),
dataType: "json",
complete: function (data) {
callpopup();
document.getElementById("test_sample_form").reset();
},
});
}
function callpopup(){
jQuery.fancybox(
'<p>Content!!!!!</p></br>',
{
padding:15,
closeBtn:true
}
);
}
</script>
Best Answer
You can use plugin or event/observer to update the success message.
In observer, Use \Magento\Framework\Message\ManagerInterface to get last added message and add new/updated success message.