LinkedIn Twitter RSS Reset

Working with AJAX in Magento

Ajax in Magento can be pretty troublesome.Because you will need to take controllers and layout into account.And I almost used up a whole day trying to make ajax work. Here are some of the steps I’d like to share so that you will not waste lots of your time, before making this work :D .
Let’s first know in Magento terms what we need.

Controller: The url on which Ajax will work on, or the request URL. You will have to set up the controller with its frontend router set in config.xml and its corresponding controller class.
Layout: Layout to handle the requested URL and return HTML if required.
Block: The block to call through layout for the above controller.

Now lets be descriptive.

If you want to show a loader while request is being processed just add the following whereever you like in the phtml page.First fetch the Javascript.

<script src="<?php echo $this->getJsUrl() ?>mage/adminhtml/loader.js" type="text/javascript"></script>

Then echo the loader which pops up. This loader will be similar to that of the admin.

<div id="loadingmask" style="display: none;">
<div class="loader" id="loading-mask-loader"><img src="<?php echo str_replace("index.php/","",$this->getUrl()) ?>skin/adminhtml/default/default/images/ajax-loader-tr.gif" alt="<?php echo $this->__('Loading...') ?>"/><?php echo $this->__('Loading...') ?></div>
<div id="loading-mask"></div>
</div>

Now to Call Ajax, use the following lines


/*Please note that the URL is created in reloadurl. Also see that the response text will be echoed in div with id=output-div*/

var reloadurl = '<?php echo $this->getUrl('router/controller/action') ?>';
Element.show('loadingmask');
new Ajax.Request(reloadurl, {
method: 'post',
parameters: "Params_Here",
onComplete: function(transport) {
Element.hide('loadingmask');
$('output-div').innerHTML = "";
$('output-div').innerHTML = transport.responseText;

}
});

After the Ajax Request is made it goes to your controller’s action, which in turn sees to your layout as follows:

class Namespace_module_frontendController extends Mage_Core_Controller_Front_Action
{
public function actionAction(){
$this->loadLayout()->renderLayout();
}
}

And here is the main part in layout where I spent most of my time in. Since in layout we will have to define reference where the html will echo (Most of the times), i got stuck here, because i need to echo the output on the div with id output-div not in any reference.And the trick is to name the layout as root and output as html. Like the following:


<module_controller_action>
<block type="module/block"  name="root" output="toHtml"  template="module/template.phtml"/>
</module_controller_action>

You are done now! What ever you write or echo in phtml file you will see populated in the DIV. Now you can treat block as normally as you do before.

Happy Coding!!

41 Responses to “Working with AJAX in Magento”

  1. Nolley
    March 3, 2010 at 11:16 pm #

    Can you explain a little more about setting the frontend router in the config file?

    Thanks,
    Jason

    • Subesh Pokhrel
      March 4, 2010 at 6:14 am #

      Routers are the path you specify to get to the controller file it is defined in config.xml with Xpath config/frontend/router and inside this Frontend name is what is used in url to get to the controller.
      Thanks

      • Nolley
        March 4, 2010 at 5:36 pm #

        I don’t think I’m doing it right.

        I created a custom module that loads into a cms page. When the user interacts with the info on the page, I am wanting to call php functions from the custom module.

        As far as I can tell, all of my code is working, but I am not getting any returned data from the ajax call.

        I added a router to my custom module config.xml

        I am very sorry to bug you, but do you have any other tips or advice?

        Thanks,
        Jason

      • Nolley
        March 4, 2010 at 8:26 pm #

        I think I have it figured out now. I just need to figure out how to control the returned data now.

        Thank you for your time!

        • Subesh Pokhrel
          March 5, 2010 at 4:03 am #

          Hi,
          Sorry I’ve n’t been able to reply your last message. So by now I think you have figured out how to get your controller going. After that you need to create a layout for that controller’s action like the layout as suggested above.

          As you can see you can specify the block type and template as well in that layout. So this will be as easy as creating a layout for any custom controller.

          And after that you should have the “output-div” (id of the div where you want to echo the response).

    • October 16, 2011 at 12:00 pm #

      I like concept of your post. Very creative post. Best of luck and waiting for some new ideas.

  2. CG
    March 23, 2010 at 10:04 am #

    Hi Subesh, first of all , thanks for the post which give me a jumpstart into Magento Ajax .
    I have followed your method, however, I got the whole page loaded into the “output-div” , instead of the block that define in the layout.

    I have tried to use $this->loadLayout(‘module_controller_action’)->renderLayout() in the actionAction , but it does not give any response.

    Actually I want to load the product list by ajax

    4

    product_list_toolbar

    Any clue ?

  3. CG
    March 23, 2010 at 10:08 am #

    It seems problem has been solved after clearing the cache. thanks …

  4. Miro Igov
    March 23, 2010 at 12:06 pm #

    Hi, it is good to mention that this Ajax object is coming with the Prototype JavaScript framework which Magento uses. Better approach in your example is using the Ajax.Updater instead of Ajax.Request because you are updating the content of a div. With Ajax.Updater you do not need the 2 lines:
    $(‘output-div’).innerHTML = “”;
    $(‘output-div’).innerHTML = transport.responseText;

    Another good option of Ajax.Updater is evalScripts ( default value is false). Setting it to true makes execution of javascript functionality within the responseText.

    Ajax.Request is good when you process JSON response or when you do not need to receive any response.

    • Subesh Pokhrel
      March 23, 2010 at 12:24 pm #

      Thanks for the Tips!

  5. April 14, 2010 at 7:48 am #

    Hi Subesh, thanks for the info.

    The updater Miro mentioned can also be run easily at set intervals as a PeriodicalUpdater:

    new Ajax.PeriodicalUpdater(‘someDiv’, reloadurl, {
    method: ‘post’,
    parameters: { from : ’10000′ },
    insertion: Insertion.Top,
    frequency: 1,
    decay: 2,
    onComplete: function() {
    Element.hide(‘loadingmask’);
    }
    });

    Sorry for lack of code formatting :-) Note: you would probably want something else to display when periodically updating than the standard loading mask which blocks the entire screen.

    • Subesh Pokhrel
      April 15, 2010 at 4:07 am #

      Thank You for the Tips!

  6. Daniel
    April 16, 2010 at 1:28 pm #

    Hi,
    great article, but Im sorry to say that I cant manage to get this to work. I do reach my controller and can see the debug data there, but I cant load the template, it just load a whole magento page. Should the block be just an empty shell without any methods? My layout-file looks like this

    [?xml version="1.0"?]
    [layout version="0.1.0"]
    [module_address_getaddresses]
    [block type="module/address_list" name="root" output="toHtml" template="module/address/list.phtml"/]
    [/module_address_getaddresses]
    [/layout]

    All help is greatly appreciated.

    • Subesh Pokhrel
      April 19, 2010 at 7:00 am #

      You are going well.. I think..and your layout files seems okai. It should work. Plz try to find out that your layout is being used or not. I guess that must be the problem or else cache might be the problem.
      Thanks.

      • Daniel
        April 20, 2010 at 8:49 am #

        Hi,
        thanks for your reply. I’ve now got it working, I was just missing the [layout][updates]-block in my config.xml for the frontend.

        Thanks again, and great article.

  7. gong gong
    April 17, 2010 at 10:10 am #

    Can you give example of getUrl(‘router/controller/action’) ?>’; in magento ?

    Thanks.

    • Subesh Pokhrel
      April 19, 2010 at 7:01 am #

      For Example if you viewing category view page then

      Router: catalog
      Controller: category
      Action : viewAction.

      Thanks.

  8. Nedo_17
    April 29, 2010 at 7:48 am #

    hey, Thanks for the great info
    i’m a new developer in magento and i was wondering, if i should create a custom module for the action and layout, or just attach it to some other module…?

    thanks

    • Subesh Pokhrel
      April 29, 2010 at 7:51 am #

      You can attach to some existing module.. It depends upon what you need.

  9. Nedo_17
    April 29, 2010 at 3:32 pm #

    I worked it out, and it’s working beautifully, thanks for the great info

  10. Madhu
    May 20, 2010 at 4:50 am #

    Hi..was going through ur ajax post..right now i have a problem..
    I am developing ajax add to cart..I have almost done it to say..I am able to add products to cart and again I am able to read the sessions of cart to mycart widget..
    the problem comes here..how do i read the image of specific product and I have to add a delete option..well u know mycart operations..
    So tel me how to get the image and delete operation..
    Or better to say how to access sidebar.phtml from root folder of magento..either one will solve the problem..

    • Subesh Pokhrel
      May 20, 2010 at 11:18 am #

      Madhu, I think you have done the “difficult” part….if you have successfully added product to cart!
      Here’s one tip for your issue, but do you have controller of your own? If yes then prepare a layout for that controller and assign block & template and… if you can access cart session as you say then showing a list of product added should not be a problem. Please the 4th and 5th snippet of code above.

      Thanks.

  11. May 26, 2010 at 1:57 pm #

    Hi Subesh,

    I want to firstly say thank you for your blog, really everytime I read something from you, you can be sure that I have learned something, and I am very greatful for that.

    Bro, I’m trying to get this ajax working, and I have override my controller and it works.

    I have added all the scripts and as far as I can see this all is working too, but bro, can you tell me what I should make the href?
    I have a bunch of tabs..and they load content dynamically but, my page load times is taking a hit, so some of these tabs I would like to bring in the content with ajax.

    My controller function looks like this:

    public function actionAction()
    		{
    			error_log('Begin action');
    
    			//Get current layout state
    			$this-&gt;loadLayout();
    
    			$this-&gt;getLayout()-&gt;createBlock(
    			'Mage_Core_Block_Template',
    			'Mage_Catalog_Block_Category_View',
    				array('template' =&gt; 'catalog/category/view.phtml')
    			);
    
    			//$this-&gt;getLayout()-&gt;createBlock('footer')-&gt;append($block);
    
    			//Release layout stream
    			$this-&gt;renderLayout();
    
    			error_log('End action');
    
    		}
    

    Can you tell me if that is correct?

    Thank you so very much man, I really appreciate it!

    impi

    • Subesh Pokhrel
      June 3, 2010 at 10:36 am #

      Hi,
      I don’t think you code will show the content, easiest way to load content is write only this in your controller

      $this->loadLayout()->renderLayout();
      

      And next prepare a layout file and follow the instruction above in the post.
      Thanks.

  12. July 1, 2010 at 4:17 pm #

    It didnt work initially for me.
    After digging in /js/mage/adminhtml/loader.js
    i had to append paramaeters with &form_key=getFormKey();?>

    like this

    parameters: ‘QueryString&form_key=getFormKey();?>’

    Let me know if this is because of some change in new magento version or if i missed any step.Anyway its working for me now

    thanks for a great post.

    • amit
      September 20, 2010 at 1:10 pm #

      Thanks friends! your post helped me great.

    • baldev
      October 22, 2011 at 9:18 am #

      I am getting the FORM_KEY not found error and not getting results. I am on magento 1.4.2.0.
      I am passing the parameter string as:

      parameters:”country_id=” + c_id + “&form_key=” + getFormKey(); ?>,

      I have tried to print this form key but nothing is printed, It is blank.
      If you can help me I will be thankful.

    • baldev
      October 22, 2011 at 9:19 am #

      @Sreekanth
      I am getting the FORM_KEY not found error and not getting results. I am on magento 1.4.2.0.
      I am passing the parameter string as:

      parameters:”country_id=” + c_id + “&form_key=” + getFormKey(); ?>,

      I have tried to print this form key but nothing is printed, It is blank.
      If you can help me I will be thankful.

  13. BIMANTAS
    October 6, 2010 at 5:04 pm #

    Hello Subesh,
    You looks very skilled man. So I decided to ask you for help.
    I am very low in magento, but want to make some changes in this web system for my wishes. I want to make “Contact us” form available like web2 style popUp accessible from any page in frontend.
    I try to do like in this link show TECHGYRRL:
    http://www.magentocommerce.com/boards/viewthread/22881/
    but this works only in “Contact us” page. Somewhere else it wouldn’t to work. I think there is some core stuff or something, but I don’t know what, because wery hard to understand magento’s ways of processing.

    In “Contacts/form.phtml” I changed form to this:
    <form name="contactForm" id="contactForm" onsubmit="new Ajax.Updater({success:'contactForm'}, 'getUrl(“contacts/index”) ?>’, {asynchronous:true, evalScripts:true, onComplete:function(request, json){Element.hide(‘contactForm’);Element.show(‘feedback’);}, onLoading:function(request, json){}, parameters:Form.serialize(this)}); return false;” action=”contacts/index” method=”post”>

    In page.xml I added block, to open it in header block:

    This is enough to poPup in any page of frontend, but mail sends only in “Contact us” page.

    Can You help me with this?

  14. john
    October 20, 2010 at 9:59 am #

    Can can anyone worked ajax on Magneto registration page.What I want to do is 3 tabs will be present in the registration page.1.Registration page,2.Option,3.Confirmation.

    After registration I should go to Option where user will select the membership and last confirmation message.

    Please help me.

  15. AK
    December 22, 2010 at 12:59 pm #

    Thanx for sharing

  16. January 17, 2011 at 3:28 pm #

    Great article, been wrestling with this for ages. Using this along with another tutorial that you did to fetch product sizes on request on the catalogue pages.

    Nice one

    Pete

  17. February 8, 2011 at 4:20 pm #

    Hi,

    Your blog is REALLY useful for magento bits, thanks.

    Can the response to the ajax call just be echoed from the controller action?? I have a lot of dynamic ‘divs’ that need updating when certain ajax calls are made?

    Thanks

    Pete

  18. April 5, 2011 at 2:44 pm #

    Instead of using a layout file (and I’m not saying this is better but it can give you more control) you can output your html straight from the controller, or more commonly bundle it up in a JSON object using json_encode in php.

    Something like this in your controller:

    $block = $this->getLayout()
    ->createBlock(‘blockname’)->setTemplate(‘blocktemplate.phtml’);

    echo $block->renderView();

    At the moment I’m building a whole set of modules to bring ajax into a load of bits of Magento, hopefully it’ll be really cool!

  19. April 26, 2011 at 2:58 pm #

    indeed, very helpful! Magento themes are very fitting for SEO. Thanks for sharing!

  20. April 28, 2011 at 11:47 am #

    Hi guys thanks for sharing amzing info,

    I have a problem where if I call mage from outside magento i get an execption. Chmod of app/ect/ files I have both at 644

    A very simple example will not work
    load($productId); //load the product
    echo $product->getSku();//get anything you want using the typical syntax
    echo $product->getPrice();
    echo $product->getShortDescription();

    ?>

  21. June 2, 2011 at 8:38 am #

    By default the loader appears whenever you do a Ajax.request in adminhtml.

    Is there a simple way to do an Ajax request in adminhtml, without triggering the loader?

    I can remove the loader.js, but then it’s removed for all requests. There are only a few non-essential requests I want to make, that should go unnoticed.

    Thanks in advance

  22. July 20, 2011 at 7:36 am #

    Thanks for the post! Stumbling upon Ajax for the first time it took a while to realize where everything should go, but I got it working in the end.

    After following the examples the Ajax request still wasn’t completing for me in Magento 1.5.1.0. The problem turned out to be the inclusion of the adminhtml loader script:

    <script src="getJsUrl() ?>mage/adminhtml/loader.js” type=”text/javascript”>

    <img src="getUrl()) ?>skin/adminhtml/default/default/images/ajax-loader-tr.gif” alt=”__(‘Loading…’) ?>”/>__(‘Loading…’) ?>

    If you experience similar problems, try removing the above lines from your template and change the JS to the following:

    var reloadurl = ‘getUrl(‘router/controller/action’) ?>’;

    new Ajax.Request(reloadurl, {
    method: ‘post’,
    parameters: “Params_Here”,
    onComplete: function(transport) {

    $(‘output-div’).innerHTML = “”;
    $(‘output-div’).innerHTML = transport.responseText;

    }
    });

  23. baldev
    October 22, 2011 at 9:23 am #

    Hello Subesh,
    I am getting FORM_KEY not defined in the js file.
    I am not getting the result in the div. only the loader is displayed.
    Have I to pass form_key also with parameters?

    I am on magento 1.4.2.0.

    Please respond soon with a solution, I will be thankful to you.

  24. Gerd
    December 4, 2011 at 5:34 pm #

    The solution for FORM_KEY problems:

    The problem occurse when using the adminhtml/loader.js.
    Following working code is without the loader:

    var reloadurl = ‘getUrl(‘yourController/yourAction/’) ?>’;
    new Ajax.Request(reloadurl, {
    method: ‘post’,
    parameters: “Your parameters go here”,
    onComplete: function(transport) {
    $(‘output-div’).innerHTML = “”;
    $(‘output-div’).innerHTML = transport.responseText;
    }
    });

Trackbacks/Pingbacks

  1. Working with Ajax and JSON Objects in Magento [Case: Ajax Powered Login Functionality] | Subesh Pokhrel's Blog - Magento Development Tips - October 26, 2010

    [...] I have written about Working With Ajax in Magento. And after a huge response I received from that post I was compelled to write more on implementing [...]

Leave a Comment