Upsell product prices not available in Magento 2 when loading the AJAX block

I am working on a Magento 2 module that uses AJAX to download upsell products. Upsell products may vary for each client, which is why AJAX is used to load a block to provide cache overkill.

For this, I have a custom module in which my block extends \Magento\Catalog\Block\Product\ProductList\Upsell . In the modules layout for catalog_product_view.xml , I have the following -

 <?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> <referenceBlock name="product.info.upsell" remove="true" /> <referenceContainer name="content.aside"> <block class="MyCompany\MyModule\Block\Product\ProductList\Upsell" name="personalised.product.upsell" template="MyCompany_MyModule::upsell.phtml" /> </referenceContainer> </body> </page> 

In my upsell.phtml -

 <div id="personalised-upsells-container" data-role="personalised-upsells"></div> <script type="text/x-magento-init"> { "*": { "MyCompany_MyModule/js/upsell": { "upsellAjaxUrl": "<?php echo $block->getUpsellAjaxUrl(); ?>" } } } </script> 

getUpsellAjaxUrl() generates http://magento2.dev/personalised/products/upsellAjax/id/6

My upsell.js is

 define([ 'jquery', 'upsellProducts' ], function($) { function getUpsellContent(url) { $.ajax({ url: url, dataType: 'html' }).done(function (data) { $('#personalised-upsells-container').html(data).promise().done(function(){ $('.upsell').upsellProducts(); }); }); } return function (config, element) { getUpsellContent(config.upsellAjaxUrl); }; }); 

My controller (upsellAjax) -

 class UpsellAjax extends ProductController { public function execute() { $productId = (int) $this->getRequest()->getParam('id'); $product = $this->loadProduct($productId); if (!$product) { return false; } /** @var \Magento\Framework\View\Result\Layout $resultLayout */ $resultLayout = $this->resultFactory->create(ResultFactory::TYPE_LAYOUT); return $resultLayout; } } 

My personalised_products_upsellajax.xml -

 <?xml version="1.0"?> <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd"> <container name="root"> <block class="MyCompany\MyModule\Block\Product\ProductList\Upsell" name="product.info.personalised.upsell" template="Magento_Catalog::product/list/items.phtml"> <arguments> <argument name="type" xsi:type="string">upsell</argument> </arguments> </block> </container> </layout> 

As expected, this correctly loads the upsell block of the product through ajax, pushes the HTML into my container, and then initializes the upsellProducts widget on the page. My upsell products show as expected, but without price.

I tried a couple of things to debug the situation, but as far as I can see, it cannot load priceRender on line 428 \Magento\Catalog\Block\Product\AbstractProduct inside the getProductPriceHtml() method. String $priceRender = $this->getLayout()->getBlock('product.price.render.default'); always returns false when a block is loaded via AJAX.

This is also the situation when I replace my block with the default block in the layout (personalized_products_upsellajax.xml), for example.

 <?xml version="1.0"?> <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd"> <container name="root"> <block class="Magento\Catalog\Block\Product\ProductList\Upsell" name="product.info.upsell" template="Magento_Catalog::product/list/items.phtml"> <arguments> <argument name="type" xsi:type="string">upsell</argument> </arguments> </block> </container> </layout> 

I thought this could have something to do with removing the upsell block first in my layout, i.e. <referenceBlock name="product.info.upsell" remove="true" /> I decided to comment on this line, which results in two upsell blocks, one of which is the default loaded block, and the other is my AJAX block. The same results when the default block shows the correct information, however my AJAX block still lacks prices.

Any help would be greatly appreciated.

+6
source share
3 answers

I had the same problem: to display prices in the layout, the product.price.render.default block should be available, as well as some of its child blocks. The idea of ​​the answer is simple: since this block is loaded for the default descriptor, make sure that this descriptor is available in the layout by adding it at the beginning of the request:

 public function __construct(Context $context, LayoutInterface $layout) { parent::__construct($context); $this->layout = $layout; $this->layout->getUpdate()->addHandle('default'); } 
+2
source

You can try:

 <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd"> <container name="root"> <block class="Magento\Catalog\Block\Product\ProductList\Upsell" name="product.info.upsell" template="Magento_Catalog::product/list/items.phtml"> <arguments> <argument name="type" xsi:type="string">upsell</argument> </arguments> </block> <block class="Magento\Framework\Pricing\Render" name="product.price.render.default"> <arguments> <argument name="price_render_handle" xsi:type="string">catalog_product_prices</argument> <argument name="use_link_for_as_low_as" xsi:type="boolean">true</argument> </arguments> </block> </container> </layout> 
0
source

I recently ran into the same problem, and after doing multiple searches and searches, we seem to have found a solution. Adding <update handle="empty"/> to the layout file seems to fix the problem and does pricing. Therefore, in your case, the layout will look like

 <?xml version="1.0"?> <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd"> <update handle="empty"/> <container name="root"> <block class="MyCompany\MyModule\Block\Product\ProductList\Upsell" name="product.info.personalised.upsell" template="Magento_Catalog::product/list/items.phtml"> <arguments> <argument name="type" xsi:type="string">upsell</argument> </arguments> </block> </container> </layout> 

I can’t start explaining why this works. I came here by looking at the 1column layout and using this as a basis. We used this to solve the problem in two different places.

0
source

All Articles