Infinite scrolling using jQuery Ajax and ASP.NET MVC
Web applications such as Facebook and Twitter use a technique known as
infinite scrolling or endless scrolling wherein data is loaded on the fly when a
user scrolls to the bottom of a web page. There are many jQuery plugins that
help you enable such a feature in your web application. However, if you wish to
avoid any third-party dependency or have some specific needs, you can add your
own infinite scrolling with a few lines of jQuery code and ASP.NET MVC. This
article tells you how that can be accomplished.
The overall logic to implement infinite scrolling is similar to Ajax driven
paging. However, unlike paging where a user explicitly clicks on a page link,
here you need to detect the scroll position and load the records automatically.
Begin by creating a new ASP.NET MVC web application. Add HomeController and
Index view to the newly created application.
Then open the Index view and add the following markup to it.
...
<body>
<div id="container"></div>
<div id="progress" style="display:none">
<h4>Loading...</h4>
</div>
</body>
The main part of the markup consists of two <div> elements - the container
where the actual data is displayed and progress indicator that is
displayed only during an ajax call.
Next, add a <script> reference to the jQuery library in the <head> section of
the Index view and also add an empty <script> block. Then add the following code
in the <script> block.
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script type="text/javascript">
var pageSize = 10;
var pageIndex = 0;
$(document).ready(function () {
GetData();
$(window).scroll(function () {
if ($(window).scrollTop() ==
$(document).height() - $(window).height()) {
GetData();
}
});
});
function GetData() {
$.ajax({
type: 'GET',
url: '/home/GetData',
data:{"pageindex":pageIndex,"pagesize":pageSize},
dataType: 'json',
success: function (data) {
if (data != null) {
for (var i = 0; i < data.length; i++) {
$("#container").append("<h2>" +
data[i].CompanyName + "</h2>");
}
pageIndex++;
}
},
beforeSend : function () {
$("#progress").show();
},
complete : function () {
$("#progress").hide();
},
error: function () {
alert("Error while retrieving data!");
}
});
}
</script>
The code declares two global variables - pageSize and pageIndex - to hold the
number of records to load at a time through an ajax call and current index of a
data page.
The ready() handler, invokes GetData() function that makes an ajax call to
the server and fetches the initial data to be displayed. This function is
discussed shortly. Notice the code marked in bold letters. This is where the
magic of infinite scrolling happens. The code wires a scroll event handler to
the window object. To decide whether a user has reached the bottom of the
scrollable region we use the scrollTop() and height() values. If user has
reached the bottom we call GetData() to retrieve the next set of records.
The GetData() function uses jQuery $.ajax() method to call GetData() action
method from the HomeController. The GetData() server side method is invoked
using a GET request and pageIndex and pageSize is passed to the server. This way
you don't need to hard-code these values in the server side code.
The success callback receives the data in the form of array. In this example
we use data from the Customers table of the Northwind database. The for loop
iterates through the data and appends CompanyName to the container <div> element
using append() method. The pageIndex is incremented for the sake of next ajax
call.
The beforeSend and complete callbacks simply show and hide the progress
indicator <div> element using show() and hide() methods. The error callback
simply displays an error message.
The GetData() server side method used by the GetData() client side function
resides in the HomeController and is shown below:
public ActionResult GetData(int pageIndex,int pageSize)
{
System.Threading.Thread.Sleep(4000);
NorthwindEntities db = new NorthwindEntities();
var query = (from c in db.Customers
orderby c.CompanyName ascending
select c)
.Skip(pageIndex * pageSize)
.Take(pageSize);
return Json(query.ToList(), JsonRequestBehavior.AllowGet);
}
The GetData() action fetches data from the Customers table. Notice the use of
Skip() and Take() to fetch only the required number of records. The records are
returned to the client side code in JSON format. This is done using Json()
methood. The Sleep() is just for the sake of testing progress indicator. You can
remove it in the production code.
That's it! Run the application and test whether it works as expected. The
following figure shows a sample run of the application:

Notice how the progress indicator is being displayed when a user scrolls to
the bottom of the window.