Ajax loading of product collection in product listing page – Magento

Today I got in to a situation where I need to do ajax loading of project collection in product listing page. if we search for the same issue on google then we will get many extensions which are free but they include plugins like infinitescroll.js, jquery.js, jquery-ui.js etc.. instead of this you can use prototype.js which is available by default in magento. Actually, this task is simple if we understand it.

By default, Magento shows product listing in page wise format. Each page numbering is a anchor tag with href which loads the complete page with new project listing related to the clicked page number.

In this example, I am going to create a simple product loading which happens whenever I click on a button. This button will be visible at the bottom of the product listing section, if the product collection is more than one page. Place this button inside {$theme}/template/catalog/product/list.phtml.This button actually triggers the “Next” functionality link which you can see in the below image:

Capture

So, whenever we click on the button this actually gets the next page product collection. If we inspect the “Next” link element (which is shown in the above image), we can see that it has two class names: next and i-next. So, to trigger click event on this element with the button we can use javascript.

<button id="load-more-products">Load more products..<button>
function sendLoadMoreProductsRequest(url) {
	new Ajax.Request(url, {
	  	onSuccess: function(response) {
	  		//Create dummy element
	  		var div = document.createElement('div');
	  		div.innerHTML = response.responseText;
	  		//refresh the page class element
	  		$$('.pages')[0].innerHTML = $(div).select('.pages')[0].innerHTML;
	  		//append the list to the existing product list
	  		$$('.category-products')[0].innerHTML += $(div).select('.category-products')[0].innerHTML;
	  		//check if there are more products to be loaded or not
	  		if(!$(div).select('.next.i-next')[0]){
	  			$('load-more-products').style.display = "none";
			}
	  	}
	});	
}

function callbackFunc(e) {
	if($$('.next.i-next')[0]){
		var nextPageUrl = $$('.next.i-next')[0].readAttribute('href');
		sendLoadMoreProductsRequest(nextPageUrl);
	}
	else{
		//hide button
		$$(e.currentTarget).hide();
	}
}

//Assigning click event to the button which triggers the "next" link
$('load-more-products').observe('click', callbackFunc);

Note: In some cases, when the category has less product collections then still the button will be visible. To hide this button add the below code inside the list.phtml template file at very end.


<script>
//<![CDATA[
    //check if there are more products to be loaded or not
    if(!$$('.next.i-next')[0]){
        $('load-more-products').style.display = "none";
    }
    function testScroll(ev){
        if($$('.scroll-to-top')[0]){
            console.log(window.pageYOffset);
            if(window.pageYOffset>400){
                $$('.scroll-to-top')[0].style.display = "block";
            }
            else{
                $$('.scroll-to-top')[0].style.display = "none";
            }
        }
    }
    window.onscroll = testScroll;
//]]>
</script>

Now just hide the default page numbering group of elements using styling properties like display: none;

This worked for me on magento 1.8. I hope this works for you too as I am not doing any big changes here :)

About these ads

20 thoughts on “Ajax loading of product collection in product listing page – Magento

  1. Hi Kamlekar,

    Mind-blowing approach man! Frankly speaking I’ve tried many free Infinite Scrollers & no one is working perfectly on my website but I tried your suggestion in this post & it some what worked for me. I’m no developer but I just did what you’ve told me. I faced two issues while implementing this –
    1) The pagination bar was recalled & shown above on the new set of loaded products.
    2) Can we add an Loading image so that the person knows something is happening.

    And one more query can we use it as an custom module & it has two benefits
    1) You can put it as an extension & anyone can get benefited out of it & thankful to you like me.
    2) No need to go & edit anything just run the beautiful app.

    I’m waiting for your response.

    • Hi Amit,

      Thanks for your comment.

      For showing a loading image while the products loading process, you can use “onLoading” function. and to hide the loading image after the products have been loaded, you can use “onComplete” function. The above two functions are in prototype and related to ajax.

      I will surely make it as an extension soon. Till then if you have any questions or doubts, regarding this article, feel free to ask here.

      • hello kamlekar i tried this but this is giving me some error error like this
        i am not able to understand this error can you help me on this issue
        Load more products..function sendLoadMoreProductsRequest(url) { new Ajax.Request(url, { onSuccess: function(response) { //Create dummy element var div = document.createElement(‘div’); div.innerHTML = response.responseText; //refresh the page class element $$(‘.pages’)[0].innerHTML = $(div).select(‘.pages’)[0].innerHTML; //append the list to the existing product list $$(‘.category-products’)[0].innerHTML += $(div).select(‘.category-products’)[0].innerHTML; //check if there are more products to be loaded or not if(!$(div).select(‘.next.i-next’)[0]){ $(‘load-more-products’).style.display = “none”; } } }); } function callbackFunc(e) { if($$(‘.next.i-next’)[0]){ var nextPageUrl = $$(‘.next.i-next’)[0].readAttribute(‘href’); sendLoadMoreProductsRequest(nextPageUrl); } else{ //hide button $$(e.currentTarget).hide(); } } //Assigning click event to the button which triggers the “next” link $(‘load-more-products’).observe(‘click’, callbackFunc);

      • Hi Rakesh,

        Thanks for your comment.

        Where can you see the error(In php or javascript)? and what is it? without the correct information I can’t help you. The code which I have provided above is just a dummy structure. The class names of the elements can change or the response text can also change. So, please debug carefully and try to understand it. It should be very simple. Good luck :)

      • Hi Kamlekar,

        Hope you are doing well, you told me to use “on loading” function & “onComplete” function to use the image, can you please guide the exact code I’ve to use since I’ve not much coding knowledge.

        Secondly, by any chance can we make this Load more products.., to load products automatically with the loading image, without pressing(clicking load more product) the button; just similar as the case of any infinite scroller works.
        If it is possible can you please guide me the exact code & their location to place?

        Thanks is advance

      • Hi amit,

        I am really sorry.
        I am very busy here. I can only give you idea how to do that. You can use “onscroll” event of javascript to load the new product list whenever the user scrolls at the end of the product list container.

        I will check and update my post on this saturday or sunday with your above query.

        As you said that you are not a developer, you can check http://www.jsfiddle.net, where you can create fiddles for your testing purpose. It will be handy for you. :)

    • Rakesh,

      There is nothing related to PHP in the above code. As you can see, I am bringing the COMPLETE PAGE as ajax response and looking for a particular class name which should be the product list container element. Then I am appending this element to the existing product list container element. This complete operation I am doing using just Javascript(prototype).

      I asked you whether the error is in php or javascript to just know is the error related to my explanation above or not.

      You still haven’t provided me error details. check “console” section in chrome browser for errors.

      If you are trying to make it work for long time then please just grab the explanation but not the code and implement it yourself using jquery or prototype.

      • Hi Rakesh,

        I’m sure you are seeing this error on the category page below the “button ” Load more products…

        the reason is that you have to write – you’ve to open & close the JavaScript now use the below code it will work–

        //

  2. Hi, trying your code but doen’t load next product in next page.
    Can you please write the correct code that you used? Or share the file list.phml?

    Thanks you

  3. hi kamlekar !! thanx for the a great tutorial

    I M facing a issue that it only renders 2 pages !! on bottom of second page when i click on load more nothing happens

    • Vishwas, my blog is only for Web developers who have good knowledge on debugging javascript by using developer tools and I think you are a shop owner. My blog is actually just an idea that this ajax loading can be done like this.. if you are a developer then please debug in chrome browser as this browser shows prototypejs errors.

      • Hey kamlekar! Thanks for the tutorial! But I seem to be too bad at coding((( Could you please recommend any extension for AJAX scroll? I found a few, and I liked the one by Amasty. But maybe you could give me some more suggestions.
        Thanks in advance!

  4. Hello kamlekar,

    Its work fine but the thing is i want only product data.
    when i scroll down it load products but when i checked in Firebug net->XHR->In Response getting whole data ( header footer left navigation product data).

    I just want when user scroll response get only product data . is it possible.
    Please suggest Me.
    Thanks

    • Yes it is possible. You should remove “$this->renderLayout();” line from the specific controller method. and instead write to send only the block section which you want. For example,

       
      $block = $this->getLayout()->getBlock('your_block_name');
      echo $block->toHtml();
      
      // $this->renderLayout(); // renders complete page
      
      
      • Hi kamlekar,

        Good tutorial, but the strange thing is that there is no renderLayout() function in ….core/Mage/Catalog/Block/Product/List.php, so I have the same problem with Swapnil D. I want to only product data or list.phtml without layout.

        Thanks,

      • Hi Blag,

        $this->renderLayout() will be in controller files. but when I did quick search, I couldn’t find even in controller files (may be it is inherited). I suggest you to create a new module and call the template list.phtml in your custom layout. So that you can access it from your custom controller function like:

            $block = $this->getLayout()->getBlock('your_block_name');
            echo $block->toHtml();
        
            // $this->renderLayout(); // renders complete page
        

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s