Infinite Scroll Using jQuery, ASP .NET MVC, Mustache and Entity Framework Paginate

0
2359
views

Infinite Scrolling is a technique widely used in websites in which page content loads continuously as the user scrolls down. You might have used the same implementation in a number of websites including Facebook, LinkedIn, almost all of the e-commerce site and many more. There are a number of benefits of adding infinite scroll to your application, some of which are :

  1. A better and engaging User experience.
  2. Increased performance, as you are loading data in chunks.

In this article we are going to implement infinite scroll using  jQuery for client side scripting, ASP .NET MVC for server side code, Mustache.js as our template engine, Entity Framework  Paginate as our pagination tool and SQL Server as our back-end.

For this example we are building a web page which shows Trekking destinations. We can filter the data based on countries and sort by difficulty of the trek, either High to Low or vice versa. We will be implementing dynamic sorting and filtering, so you can extend the additional filters or sorting as per your need.

Our data table is called Treks and contains all the data we need to display to the users.

InfiniteScroll-DB

Let’s begin by designing our front-end. We have an empty div with id trekDataDiv, which will store all the generated data. The reason it is empty right now is because we are using Mustache js for template and we will be filling this div with the rendered template. We also have a loader, which we will turn on and off while loading the data.

<div class="mdl-cell mdl-cell--8-col">
    <!-- Div to load rendered template data. -->
    <div id="trekDataDiv"></div>
    <!-- MDL Progress Bar with Indeterminate Progress -->
    <div id="loader" class="mdl-progress mdl-js-progress mdl-progress__indeterminate"></div>
</div>

Now, we need to create our template which will be repeated over to show our trekking details.

{{#treks}}
<div class="demo-card-wide mdl-card mdl-shadow--2dp">
   <div class="mdl-card__title" 
         style="background: url('/Assets/{{ImageName}}') center / cover">
         <h2 class="mdl-card__title-text">{{Name}}</h2>
   </div>
   <div class="mdl-card__supporting-text">
         Country : {{Country}}
         <br/>
         Difficulty : {{Difficulty}}
         <br />
        {{Description}}
   </div>
   <div class="mdl-card__actions mdl-card--border">
         <a class="mdl-button mdl-button--colored mdl-js-button mdl-js-ripple-effect">
            View Details
         </a>
   </div>
</div>
<br />
{{/treks}}

InfiniteScroll-TrekCard

To briefly explain, we are iterating over Json array treks with properties (Name, Country, Description, etc). Mustache js will take care of iterating and binding the data and produce the required html (shown in the image), which we will append to the empty div trekDataDiv.

Mustache takes and identifies the properties to bind by locating them inside curly braces. To get a better understanding of Mustache check this link.

 

To give our UI some brains, we need to add some jQuery.

$(document).ready(function () {

    var trekCardTemplate,
        isLoading = false,
        pageNumber = 0,
        trekData = {
            treks: []
        };

    function appendTrekData(data) {
        $.get(
            '/Content/TrekCardTemplate.html',
            function (template) {
                trekCardTemplate = template;
            }
        );
        $(document).ajaxStop(function () {
            var renderedPage = Mustache.to_html(trekCardTemplate, data);
            $("#trekDataDiv").append(renderedPage);
            data.treks = [];
        });
    }

    function getTrekData(country, sortBy) {
        if (!isLoading) {
            $("#loader").show();
            isLoading = true;
            pageNumber++;
            $.get("/JqueryExample/GetTreks?pageSize=2&currentPage=" +
                pageNumber + "&countryName=" + country + "&sortBy=" + sortBy,
                function (data) {
                    if (data != '') {
                        trekData.treks = data.Results;
                        appendTrekData(trekData);
                    }
                    isLoading = false;
                    $("#loader").hide();
                });
        }
    };

    $('.mdl-layout__content').on('scroll', function () {
        if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight - 1) {
            getTrekData("", 1);
        }
    });

    // Initialise page and load trekking data's page.
    var initPage = function () {
        getTrekData("", 1);
    }();
})

Our getTrekData function gets the data from server and passes it to appendTrekData function, which fetches the template and fills it with the data. We send page size to set the specified number of results sent from server, current page for which data needs to be fetched, country name to filter data based on country and sort by value to determine the sort order of the result.

EFP_Logo

Now, our last and final step is to write the server side code to fetch data from database and pass it on to client. We need to set our filter, so that when a country name is sent, the treks for that particular country are returned. Also, for sorting we need to order the result set by ascending or descending order of difficulty based on user input.

So, to implement dynamic sorting and filtering with pagination, we are using a free open-source plugin Entity Framework Paginate. Here goes the function to get the data.

public Page<Trek> GetFilteredPagedTreks(int pageSize, int currentPage, string countryName, int sortBy)
{
        Page<Trek> treks;
        var filters = new Filters<Trek>();
        filters.Add(!string.IsNullOrEmpty(countryName), x => x.Country.Equals(countryName));
        var sorts = new Sorts<Trek>();
        sorts.Add(sortBy == 1, x => x.DifficultyLevel);
        sorts.Add(sortBy == 2, x => x.DifficultyLevel,true);

        using (var context = new PlacesEntities())
        {
             treks = context.Treks.Paginate(currentPage, pageSize, sorts, filters);
        }

        return treks;
}

To get an in depth knowledge of the plugin EF Paginate, check this link. And with this implementation, we have our working infinite scroll ready.

To check the complete source code click here.

InfiniteScroll