How to Render an HTML Using an Ajax Call in Magento 2 Module
In the previous article, we have displayed the form success action message using ajax. In that article, we have returned only the specific message from our controller and display it on the frontend. Sometimes you need to return the whole HTML and display it on frontend using Ajax. Today we will see How to render an HTML using an Ajax call in Magento 2 Module.
Magento 2 provides a Magento\Framework\Controller\Result\JsonFactory
class that can be use to return an JSON response from a controller. We will use factory method of this class to return our HTML in json format.
Create PHTML File
Create a PHTML file index.phtml under app/code/Codextblog/Custom/view/frontend/templates
from where we want to initialize our ajax call.
<div id="ajaxresponse"></div> <?php $ajaxurl = $block->getAjaxUrl(); ?> <script type="text/x-magento-init"> { "*": { "Codextblog_Custom/js/custom": { "AjaxUrl": "<?php echo $ajaxurl; ?>", "CurrentProduct": "<?php echo $currentProductId; ?>", } } } </script>
In this file, we have created one blank div with id #ajaxresponse. Using ajax call we will call controller file and return an HTML. Using JQUERY we will fill that HTML into div.
Under the script tag, we are passing two parameters to our js file. First is AjaxUrl which is the URL of the controller (in our case it is custom/index/view/, a custom is the front name of our module and view.php is our controller file) from where we will return a JSON response, second is CurrentProduct which is product id. You can pass any other parameters in this call. For demonstration purpose, we have passed product id to CurrentProduct parameter.
Create JS File
Create a JS file custom.js under app/code/Codextblog/Custom/view/frontend/web/js
directory and enter below code.
define([ "jquery", "jquery/ui" ], function($){ "use strict"; function main(config, element) { var $element = $(element); var AjaxUrl = config.AjaxUrl; var CurrentProduct = config.CurrentProduct; $(document).ready(function(){ setTimeout(function(){ $.ajax({ context: '#ajaxresponse', url: AjaxUrl, type: "POST", data: {currentproduct:CurrentProduct}, }).done(function (data) { $('#ajaxresponse').html(data.output); return true; }); },2000); }); }; return main; });
You can see, in the done method we are filling the div content using data.output, that contains the actual HTML.
Create Controller File
Create a controller file View.php under app/code/Codextblog/Custom/Controller/Index
directory and write below code
<?php namespace Codextblog\Custom\Controller\Index; use Magento\Framework\App\Action\Action; use Magento\Framework\App\Action\Context; use Magento\Framework\Controller\Result\JsonFactory; use Magento\Framework\View\Result\PageFactory; class View extends Action { /** * @var PageFactory */ protected $_resultPageFactory; /** * @var JsonFactory */ protected $_resultJsonFactory; /** * View constructor. * @param Context $context * @param PageFactory $resultPageFactory * @param JsonFactory $resultJsonFactory */ public function __construct(Context $context, PageFactory $resultPageFactory, JsonFactory $resultJsonFactory) { $this->_resultPageFactory = $resultPageFactory; $this->_resultJsonFactory = $resultJsonFactory; parent::__construct($context); } /** * @return \Magento\Framework\Controller\Result\Json */ public function execute() { $result = $this->_resultJsonFactory->create(); $resultPage = $this->_resultPageFactory->create(); $currentProductId = $this->getRequest()->getParam('currentproduct'); $data = array('currentproductid'=>$currentProductId); $block = $resultPage->getLayout() ->createBlock('Codextblog\Custom\Block\Index\View') ->setTemplate('Codextblog_Custom::view.phtml') ->setData('data',$data) ->toHtml(); $result->setData(['output' => $block]); return $result; } }
You can see, in the line no. 54 and 55 we have passed block file and template file in which we will write our business logic and HTML code respectively. We have passed the currentproductid in setData method so that it is available in block file for any business logic. In line number 59 we are setting our data in setData method which is preparing JSON output.
Create Block File
Create View.php under app/code/Codextblog/Custom/Block/Index
directory and write below code
<?php namespace Codextblog\Custom\Block\Index; use Magento\Framework\View\Element\Template; class View extends Template { public function __construct(Template\Context $context, array $data = []) { parent::__construct($context, $data); } protected function _prepareLayout() { return parent::_prepareLayout(); // TODO: Change the autogenerated stub } public function getProducts($productId) { ---------------ANY BUSINESS LOGIC--------- return; } }
Create Template File
Create view.phtml file under app/code/Codextblog/Custom/view/frontend/templates
directory with your HTML code.
<?php $productData = $block->getData(); $productId = $productData['data']['currentproductid']; $products = $block->getProducts($productId); ?> <div> <div>YOUR HTML</div> </div>
You can see here currentproductid is available in our template file. Using that variable we can fetch any business logic from block file and render an HTML code in our template file.
Hope this AJAX tutorial will help you in your project. Please like us on Facebook and follow us on Twitter.
Leave a Comment
(3 Comments)
How does full page cache affect ajax queries like this? Will the response be cached if I want to return customer specific data, e.g. show info specific to the customer on product page which should not be cached and shown to other customers!
In POST Ajax request, response will never cache in fpc. In each and every request you will get non cacheble response.
Sorry last comment posted before I could correct.
The dom ready jquery call seems pointless. It is inside a main function and you can also use ‘domReady!’ in the require. You are welcome to correct me if I am missing something.
Useful Magento 2 Articles
Author Info
Chirag
Connect With MeWas this post helpful? Please support Us!
To Avoid Spam Downloads, We Want Your Email
away. Please submit form below.
Magento 2
Knowledge
to your Inbox