Magento Ajax - how to programmatically display custom block from Controller (my HTML content is always blank)
I find these things very difficult. I am going to try to answer in two parts:
PART ONE
You may want to try to render the layout in the controller so try this first then read the additional items below:
//file: app/code/local/MyModule/Ajax/controllers/ProductController.php
//class: MyModule_Ajax_ProductController
//function: indexAction()
$this->loadLayout();
$this->renderLayout();
BUT you are making an Ajax module. So you might want to utilise controller methods such as:
//set the response
$this->getResponse()
//->clearHeaders()
->setHeader('Content-Type', 'application/json')
->setBody(json_encode($someReturnObject));
return;
And if you want to setBody()
to a block's HTML then in the controller the code you have posted above is looking good (but see part two below):-
$this->loadLayout();
$myBlock = $this->getLayout()->createBlock('ajax/product');
$myBlock->setTemplate('mymodule_ajax/product.phtml');
$myHtml = $myBlock->toHtml(); //also consider $myBlock->renderView();
$this->getResponse()
->setHeader('Content-Type', 'text/html')
->setBody($myHtml);
return;
And actually even just calling exit();
at the end of indexAction()
will flush the PHP output buffer to the browser.
I note that you are making a product controller. Studying the code in the class you are extending may help:
//file: app/code/core/Mage/Catalog/controllers/ProductController.php
//class: Mage_Catalog_ProductController
//function: viewAction()
public function viewAction()
{
// Get initial data from request
$categoryId = (int) $this->getRequest()->getParam('category', false);
$productId = (int) $this->getRequest()->getParam('id');
$specifyOptions = $this->getRequest()->getParam('options');
// Prepare helper and params
$viewHelper = Mage::helper('catalog/product_view');
$params = new Varien_Object();
$params->setCategoryId($categoryId);
$params->setSpecifyOptions($specifyOptions);
// Render page
try {
$viewHelper->prepareAndRender($productId, $this, $params);
} catch (Exception $e) {
//...
}
}
which might give you some ideas about sending Magento-standard product-related HTML to the browser. You may find the prepareAndRender()
helper function more interesting but ultimately it uses $this->renderLayout()
to create the output html (here $this
is the controller).
PART TWO
I think you need to concentrate on the line in your code:
echo $this->getLayout()->createBlock('ajax/product')->setTemplate('mymodule_ajax/product.phtml')->toHtml();
and either change it to
echo $this->getLayout()->createBlock('mymodule_ajax/product')->setTemplate('mymodule_ajax/product.phtml')->toHtml();
or, in your module's config.xml file add something like: (I think this is the answer you need)
<config>
<global>
<!-- ... -->
<blocks>
<ajax>
<class>MyModule_Ajax_Block</class>
</ajax>
</blocks>
<!-- ... -->
</global>
</config>
so that Magento can understand that createBlock('ajax/product')
means MyModule_Ajax_Block_Product
and not Mage_Ajax_Block_Product
.
I also recommend you change MyModule
to Mymodule
throughout so that there is not a capital letter in the middle. Because
$this->getLayout()->createBlock('mymodule_ajax/product')
well, I don't understand the fine details but generally Magento will make mymodule
into Mymodule
not MyModule
Does that make sense?
Natacha Beaugeais
Updated on June 04, 2022Comments
-
Natacha Beaugeais almost 2 years
I am trying to display a block as part of a response to an ajax call. Everything is working except I cannot get the controller to echo the template HTML code.
My module class:
class MyModule_Ajax_ProductController extends Mage_Catalog_ProductController { public function indexAction() { if ($product = $this->_initProduct()) { echo '<div>hello</div>'; //this works echo $this->getLayout()->createBlock('ajax/product')->setTemplate('mymodule_ajax/product.phtml')->toHtml(); //I also tried: //$layout = $this->getLayout(); //$update = $layout->getUpdate(); //$update->load('ajax_product_index'); //$layout->generateXml(); //$layout->generateBlocks(); //$output = $layout->getOutput(); //echo $output; } } }
Inside my template file product.phtml - this HTML never gets shown. (saved to app/design/frontend/default/default/template/mymodule_ajax/product.phtml)
<div>HERE!</div>
My block class:
class MyModule_Ajax_Block_Product extends Mage_Catalog_Block_Product { private $product; protected function _construct() { parent::_construct(); $this->setTemplate('mymodule_ajax/product.phtml'); } protected function _toHtml() { return parent::_toHtml(); } public function setProduct($product) { $this->product = $product; return $this; } public function getProduct() { return $this->product; } }
My layout/mymodule_ajax.xml
<?xml version="1.0"?> <layout> <ajax_product_index> <reference name="root"> <block type="ajax/project" name="root" output="toHtml" template="mymodule_ajax/product.phtml"/> </reference> </ajax_product_index> </layout>
I am assuming that because I am setting up the template programmatically in my block class I shouldn't need the module reference? Removing the reference makes no difference.
I get no PHP errors, the HTML displayed renders
<html> <head></head> <body></body> </html>
I simply can't figure out what I am doing wrong? I'm using Magento CE 1.8.1
-
Natacha Beaugeais almost 10 yearsThis all makes sense, yes - thank you so much for all the detail. I am going to go through this now with a fine toothed comb. Hopefully one of your answers help me and saves my sanity... I will get back to you on this soon.
-
Natacha Beaugeais almost 10 yearsTHANK YOU. Your detailed answer, explanations etc led me down the path to a resolution. In the end, it was the naming of my block in the code, and the incorrect naming of my template file and folder structure - The system couldn't finding my template but instead of telling me so, it was returning an empty string. This one was super hard to track and debug!!