JQuery Addons: dataTables (a JQuery GridView)

As a .Net developer who likes a screaming fast user interface, programming in .Net can be frustrating if you are one of the teeming millions that use a GridView.  Perhaps you’ve dabbled in .Net extensions over the years such as Infragistics, Telerik, or DotNetNuke.  If you were not satisified with any of that, you probably were very happy when you found JQuery, and like a beacon in the fog you stumbled towards the subsonic AJAX calls they had told us about years ago…

As great as JQuery is though, it’s not easy to do everything you want out of the box.  Enter Allan Jardine’s wonderful add-on: DataTables.  It’s really just that.  A “magical” link between your well defined HTML tables and four ways to populate them with data really quickly.

This walk through will discuss the necessary pieces to incorporate this.  It also builds off a previous blog, JQuery to web service ajax, so I’ll skip the details around that.

First thing you need is to link to the following files or download them:

Now you need to do some prep work to get the table squared away.  First, define your target HTML table:

         <table id="tblAwesomeSauce" width="700px">
        <thead>
        <tr>
        <th>Header 1</th>
        <th>Header 2</th>
        <th>Header 3</th>
        <th>Header 4</th>
        <th>Header 5</th>
        <th>Header 6</th>
        <th>Header 7</th>
        <th>Header 8</th>
        </tr>
        </thead>
        <tbody id="tblAwesomeSauce-body">
        <tr>
        <td colspan="4" class="dataTables_empty">
        Loading data from server
        </td>
        <td />
        <td />
        <td />
        <td />
        <td />
        <td />
        <td />
        </tr>
        </tbody>
        </table>
        <div id="tblAwesomeSauce-noresults">There is no data</div>

 

Now, we’re going to jump to the bottom of your page and create the Template columns for later use.  Two things of note: Put it below the </Form> tag and don’t be sad when Intellisense does not pick this up.

    <script id="tblAwesomeSauce-row" type="text/html">
      <tr>     
<td><a href='#' onclick='openPopUp1(${value1},${value2}); return false;' >Click here 1</a></td>
<td><a href='#' onclick='openPopUp2(${value1},${value2}); return false;' >Click here 2</a></td>
<td>${value1}</td>
<td>${value2}</td>
<td>${value3}</td>
<td>${value4}</td>
<td>${value5}</td>
<td>${value6}</td>    
      </tr>
    </script>

CAVEAT! If the number of columns between your HTML table header/rows and your Template row do not match, your data will likely not show up, and you will be sad that you forgot this simple gotcha.

Create a button or something to wire this event up to, and then let’s head up to your JQuery code.  Here’s what a complete set of instructions could look like.  Take a look and then we’ll discuss them:

<script language="javascript" type="text/javascript">
        $(document).ready(function () {
            //For more info on wiring up a GridView OnClick event to get the row id: 
            //http://aspdotnetcodebook.blogspot.com/2010/01/page-languagec-autoeventwireuptrue.html
            $('#<%# radGrid1.ClientID %>').find("tr").click(function (event) {
                var id = $(this).find("td:first").text();
                fillGrid(id);
            });
            $('#tblAwesomeSauce').dataTable({
                bJQueryUI: true,
                bFilter: false,
                bPaginate: false,
                bSort: false,
                bInfo: false
            });
        });
        function fillGrid(id) {
            $.ajax({
                type: 'POST',
                url: 'yourWebService.asmx/GetData,
                data: "{id:'" + id + "'}",
                contentType: 'application/json; charset=utf-8',
                dataType: 'json',
                success: function (msg) {
                    fillGridSucceeded(msg);
                    setTimeout("fillLoansGrid(id)", 30000);
                },
                error: function (xhr, ajaxOptions, thrownError) {
                    //alert(xhr.status);
                    //alert(thrownError);
                }
            });
        }
        var fillGridSucceeded = function (result) {
            var data = result.d;
            var dt = $('#tblAwesomeSauce').dataTable({ bRetrieve: true });
            dt.fnDestroy();
            $("#tblAwesomeSauce-body").empty();
            if (result.d.length == 0) {
                $("#tblAwesomeSauce-noresults").show();
                $("#tblAwesomeSauce").hide();
            } else {
                $("#tblAwesomeSauce-noresults").hide();
                $("#tblAwesomeSauce").show();
                $("#tblAwesomeSauce-row").tmpl(data).appendTo("#tblAwesomeSauce-body");
                $('#tblAwesomeSauce ').dataTable({
                    bJQueryUI: true,
                    bFilter: false,
                    bPaginate: false,
                    bInfo: false,
                    "sScrollY": "500px",
                    aaSorting: [[3, 'asc']]
                });
            }
        };
    </script>

If you are used to making AJAX calls with JQuery, kudos to you, if you’re not, here’s a breakdown of what’s happening at a high level. When they click on a row in the GridView (Telerik RadGrid actually), the following code will grab the ID field and call the next function:

            $('#<%# radGrid1.ClientID %>').find("tr").click(function (event) {
                var id = $(this).find("td:first").text();
                fillGrid(id);
            });

fillGrid is your average JQuery AJAX call to a Web Service.  You set up your call, throw it a value, and setup it’s success and failure options:

         function fillGrid(id) {
            $.ajax({
                type: 'POST',
                url: 'yourWebService.asmx/GetData,
                data: "{id:'" + id + "'}",
                contentType: 'application/json; charset=utf-8',
                dataType: 'json',
                success: function (msg) {
                    fillGridSucceeded(msg);
                    setTimeout("fillLoansGrid(id)", 30000);
                },
                error: function (xhr, ajaxOptions, thrownError) {
                    //alert(xhr.status);
                    //alert(thrownError);
                }
            });
        }

fillGridSucceeded is where the dataTable and Template magic happen.

         var fillGridSucceeded = function (result) {
         var data = result.d;
         var dt = $('#tblAwesomeSauce').dataTable({ bRetrieve: true });
         dt.fnDestroy();

These four lines get back the results from your WebService in JSON format (so, like a JavaScript object with a bunch of string variables would be an easy way to test this out).  Then it gets hold of the HTML table and summarily destroys it’s contents so we don’t get confused.  Then we’ll skip down to the else statement where the work happens:

         $("#tblAwesomeSauce-row").tmpl(data).appendTo("#tblAwesomeSauce-body");
         $('#tblAwesomeSauce ').dataTable({
            bJQueryUI: true,
            bFilter: false,
            bPaginate: false,
            bInfo: false,
            "sScrollY": "500px",
            aaSorting: [[3, 'asc']]

This takes the JSON object and tries to smash it into the HTML Template you defined at the bottom of your page.  Then it appends that to the HTML table’s body tag.  The rest are various settings to do stuff likfe Y-axis scrolling and custom sorting or paging.

You may want to see the Web Service – Data Layer code for this example, but suffice to say, all it does is return the data as a List<Class>.  That <Class> is simply 8 string variables.  DateFields and Dollar amounts I converted into strings for this example to see what the dataTable extensions would do.  What does it do?  Well, by default it will attempt to auto-detect your types and it does that fairly well in it’s Sorting procedures.  Want to break it?  No problem; it’s fairly simple to confuse.  Try prefixing your dollar amounts with a $, then it will auto detect that back into a normal string.  There’s a lot of annoying details at this level, so, I’ll stop there.  Using LINQ to return an [object] from Entity Framework’s also works quite nicely.

Why bother?  In the words of Anthony Burgess: “O my little brothers”, because it is fast and it is the “very height of fashion”.

Enjoy

© Copyright Duke Hall - Designed by Pexeto