0

I have added a checkout step to my store where i want cross sell products. I have this block that is on the cart page for cross sell products which i would like to add in however my step is just a html file.

                <block class="Magento\Checkout\Block\Cart\Crosssell" name="checkout.cart.crosssell" template="Magento_Catalog::product/list/items.phtml" after="-">
                    <arguments>
                        <argument name="type" xsi:type="string">crosssell</argument>
                    </arguments>
                    <block class="Magento\Catalog\Block\Product\ProductList\Item\Container" name="crosssell.product.addto" as="addto">
                        <block class="Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare"
                               name="crosssell.product.addto.compare" as="compare"
                               template="Magento_Catalog::product/list/addto/compare.phtml"/>
                    </block>
                </block>

So as suggested i am going to create a controller for cross sell and then call this controller using ajax and place into my html with javascript.

<?php
namespace Harri\HelloWorld\Controller\Index;

use Magento\Framework\Controller\ResultFactory;

class Display extends \Magento\Framework\App\Action\Action
{
protected $resultPageFactory;

/**
 * Constructor
 * 
 * @param \Magento\Framework\App\Action\Context  $context
 * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
 */
public function __construct(
    \Magento\Framework\App\Action\Context $context,
    \Magento\Framework\View\Result\PageFactory $resultPageFactory

)
{
    $this->resultPageFactory = $resultPageFactory;
    $this->_resultFactory = $context->getResultFactory();
    parent::__construct($context);
}

/**
 * Execute view action
 * 
 * @return \Magento\Framework\Controller\ResultInterface
 */
public function execute()
{
    $resultLayout = $this->resultFactory->create(ResultFactory::TYPE_LAYOUT);
    return $resultLayout;
}
}

However i am currently having issues with the controller and rendering the block from xml. This needs to use below code to render the block however am not quite sure how to use it in the controller to generate my cross-sell block.

$resultLayout = $this->resultFactory->create(ResultFactory::TYPE_LAYOUT);
return $resultLayout;

I can echo hello world out into my controller however cannot get my controller to render the block from the xml. Also having a lot of difficulty getting the controller to just be a blank layout with just my cross-sell block.

XML: (using a differnt block at present for testing as have not setup crosssell on this site i ma testing on)

<?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" label="Root">
        <block class="Magento\Cms\Block\Block" name="homeslider">
                <arguments>
                    <argument name="block_id" xsi:type="string">homeslider</argument>
                </arguments>
            </block>
</container>

I have created a github with progress so far with following issues:

  1. Block called from the controller redirects to controller page. Want to either have this redirect to cart when adding a product from controller or use ajax add to cart from checkout.

  2. Checkout step shows both my step and the next step on same page and both highlighted when loading /checkout. I think this may be due to my module requiring dependency on magento_checkout however cant see in docs how to do this.

  3. My other issue once this is all working is hiding the step if there are no cross sells or showing another block in place in this step. Will try and check weather this is empty before the checkout loads and disable the step in the js however worried about page speed with loading controller twice.

2

If you want to call a block in html file, AJAX loading the content is the way to it. Magento 2's export functionality does the same thing. When you change export entity magento has to change filter html that is rendered. so magento calls this Controller

Magento\ImportExport\Controller\Adminhtml\Export\GetFilter

Observe the code in execute method. There are two key things

 $resultLayout = $this->resultFactory->create(ResultFactory::TYPE_LAYOUT);
return $resultLayout;

So you are going to return a layout and NOT a page layout.

Name of your xml will be .xml That means you will create a xml like this

<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd">
<container name="root" label="Root">
           <block class="Magento\Checkout\Block\Cart\Crosssell" name="checkout.cart.crosssell" template="Magento_Catalog::product/list/items.phtml" after="-">
                <arguments>
                    <argument name="type" xsi:type="string">crosssell</argument>
                </arguments>
                <block class="Magento\Catalog\Block\Product\ProductList\Item\Container" name="crosssell.product.addto" as="addto">
                    <block class="Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare"
                           name="crosssell.product.addto.compare" as="compare"
                           template="Magento_Catalog::product/list/addto/compare.phtml"/>
                </block>
            </block>
</container>

Notice that parent node is and not That's it. You will have your cross sell html as response to your ajax request. Just insert the html wherever you want.

To an ajax call you can write jquery inside your html. somthing like this

<script>
require(['jquery'],function($){
   $.get('url/of/controller',function(response){
      //do stuff with your html
   })
})
<script>

If you knockout do with knockout. Or doing it with x-magento-init is even better.

Just start with a simple echo "Hello world" in your controller and it will become clear. If your controller action is route/controller/action then your layout name should be route_controller_action.xml . That's why result factory knows which layout.xml to use from your module

  • Ok this sounds good however i am slightly confused as to how make the ajax call within the html page to get this block? – harri May 10 '17 at 13:45
  • Thanks but im still a little lost. So i need to write a controller for crosssell that returns a layout? What is the XML for here? and then in my html i call this new controller that returns that layout and update this into my html? – harri May 10 '17 at 14:09
  • Yeah this is brilliant so i think i undersatnd what i am kinda doing. So i create a controller that is going to be an empty crosssell page. This controller has the xml you stated so that it renders the crosssell list. This can then be accessed on that url and i just do some jquery to spit this out on the page. However my controller.php is not showing my block as stated in xml and my html file isnt running the javascript what is going in the controller? I have updated my answer to show what i am doing – harri May 10 '17 at 15:15
  • Yeah i think i need to do a bit of ground work just to get the controller sorted in a normal view just looking over that code now. Javascript wise nothing is showing in console but will leave this for now. – harri May 10 '17 at 15:40
  • I have the javascript side working however just stuck on controller now... I have tried just creating a controller to show the crosssell list without any luck any chance of an example controller :P as when i drop the code suggested in i just get errors? – harri May 10 '17 at 17:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.