I had a similar problem: I wanted the mini-cart component to refresh after I sent an Ajax request to add an item the cart.
It actually works quite nicely if you just remember some points:
- Declare which page sections need to be updated after an Ajax call, in etc/frontend/sections.xml of your module.
- Use jQuery.post() to send your Ajax request. It may be a POST or a PUT request, just not GET.
- And it must be through jQuery, not Prototype or vanilla JS, because it is jQuery's 'ajaxComplete' event that plays an essential role.
- prepend the Ajax url with a base-url (do not just start with /)
Here is my sections.xml (xyz is the name of our customer):
<?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="xyz-ajax/cart/add">
<section name="cart"/>
</action>
</config>
Here, 'xyz-ajax/cart/add' is according to the format '[frontName]/[ActionPath]/[ActionName]'. The xml tells Magento to update 'cart' after ajax call "xyz-ajax/cart/add" has completed.
This is my template (.phtml) code:
<script type="text/javascript">
require(['jquery', 'BigBridge_XYZ/option_selector'], function($, optionSelect) {
optionSelect.create(<?= json_encode($componentData) ?>, $);
})
</script>
and this is the JS code that sends the Ajax request:
function requestComplete(responseData) {
}
$.post(baseUrl + 'xyz-ajax/cart/add/cf/' + configurableProductId + '/simple/' + item.simpleProductId + '/amount/' + item.amount, requestComplete);
What happens in the process?
Every time your script sends an Ajax POST (or PUT) request to the server via jQuery, and it returns, jQuery sends an 'ajaxComplete' event. This event is handled by a handler in module-customer/view/frontend/web/js/customer-data.js. This handler checks which page-sections depend on the Ajax call (from your sections.xml) and invalidates them. These will be updated.
Sources:
Usually the best place to start looking is at the place where it's used. In this case, the onepage checkout.
If you look at public/vendor/magento/module-checkout/view/frontend/templates/onepage.phtml
you'll note the following line:
window.checkoutConfig = <?php /* @escapeNotVerified */ echo \Zend_Json::encode($block->getCheckoutConfig()); ?>;
Ergo, if you want to have this configuration anywhere else you need to include this in your template as well. If you take a look at the getCheckoutConfig()
-method of Block/Onepage.php
you'll see:
/**
* Retrieve checkout configuration
*
* @return array
* @codeCoverageIgnore
*/
public function getCheckoutConfig()
{
return $this->configProvider->getConfig();
}
On it's turn $this->configProvider
maps to Magento\Checkout\Model\CompositeConfigProvider
. Now, if you just re-use this model in your own block class using dependency injection you can simply mimic the same code in your own class:
/**
* @var \Magento\Checkout\Model\CompositeConfigProvider
*/
protected $configProvider;
/**
* Constructor call.
* @param Template\Context $context
* @param \Magento\Checkout\Model\CompositeConfigProvider $configProvider
* @param array $data
*/
public function __construct(
Template\Context $context,
\Magento\Checkout\Model\CompositeConfigProvider $configProvider,
array $data = []
)
{
$this->configProvider = $configProvider;
parent::__construct($context, $data);
}
/**
* Retrieve checkout configuration
*
* @return array
*/
public function getCheckoutConfig()
{
return $this->configProvider->getConfig();
}
Now you can use getCheckoutConfig()
in your own template/block as well:
<script type="text/javascript">
window.checkoutConfig = <?php echo \Zend_Json::encode($block->getCheckoutConfig()); ?>;
</script>
Best Answer
You can check this answer out:
Magento 2: Syncing Backend and Frontend State/Cache
Here's an example how to use customer-data:
Hope this'll help you out.