Introduction

Another weekend, another bit of testing to do. Lately I have been doing a lot of webdev so I am looking to improve my skills and test things during the weekend. Last weekend I tested jtable and even have it in production. But we are always on the lookout for better and it was suggested to me to try datatables. Which I did.

Installation

Documentation for datatables is kind of lacking in that it leaves out important information to get all the bits working.

So here is the list of nuget packages I used.

  • jQuery 1.9.0
  • jquery.datatables 1.9.4
  • jQuery.UI.Combined 1.10.0
  • Nancy 0.15.3
  • Nancy.Hosting.Aspnet 0.15.3
  • Nancy.Viewengines.Razor 0.15.3

One thing that is on nuget but does not really work are the jquery-ui themes for the themeroller. But not to worry you can download them from the site and just add them manually (yuck).

Don’t forget to copy your Scripts folder to the Content folder. Not sure if I can tell nuget how to do this in future but that would be nice. Anyway.

Now we have all the bits. Here is the code.

Nancy

I will use my PlantModel from the previous blogpost.

But I will have to change my PLantsmodule to look like this.

using System;
using System.Collections.Generic;
using System.Linq;
using Nancy;
using Nancy.ModelBinding;
using NancyJTable.Models;
using System.Linq;

namespace NancyJTable.Modules
{
    public class PlantsModule:NancyModule
    {
        public PlantsModule()
        {
            Get["/"] = parameters => View["Plants"];
            Get["/plants/{Id}"] = parameters => View[GetPlantModels().SingleOrDefault(x => x.Id == parameters.Id)];
            Get["/plants"] = parameters =>
                {
                    int start = Convert.ToInt32(Request.Query.iDisplayStart.ToString());
                    int length = Convert.ToInt32(Request.Query.iDisplayLength.ToString());
                    var totalRecords = GetPlantModels().Count;
                    var secho = Request.Query.sEcho;
                    var sorting = Request.Query.sSortDir_0;
                    if (sorting == "asc")
                    {
                        return Response.AsJson(new { aaData = GetPlantModels().OrderBy(x => x.Id).Skip(start).Take(length), sEcho = secho, iTotalRecords = totalRecords, iTotalDisplayRecords = totalRecords });
                    }
                    else
                    {
                        return Response.AsJson(new { aaData = GetPlantModels().OrderByDescending(x => x.Id).Skip(start).Take(length), sEcho = secho.ToString(), iTotalRecords = totalRecords, iTotalDisplayRecords = totalRecords });
                    }
                };
        }

        private IList<PlantModel> GetPlantModels()
        {
            var plantModels = new List<PlantModel>();
            for (var i = 1; i <= 25; i++)
            {
                var j = i.ToString("000");
                plantModels.Add(new PlantModel()
                {
                    Id = i,
                    Name = "name" + j,
                    Genus = "genus" + j,
                    Species = "Species" + j,
                    DateAdded = DateTime.Now
                });
            }
            return plantModels;
        }
    }
}```
See how use a Get? See how I get the paging parameters (iDisplayStart and iDisplayLength). I only allow the user to resort the Id column so I am slightly cheating here. You can find all [the parameters here.][5] You also need to get sEcho and just pass it back out. 

The output will look something like this in json.

{ “sEcho”: 3, “iTotalRecords”: 57, “iTotalDisplayRecords”: 57, “aaData”: [ { “Id”: “1”, “Name”: “Name1”, “Genus”: “Genus1”, “Species”: “Species1”, “DateAdded”: “”, }, … ] }``` Which is an objectnotation. Let’s remember that fact because it is pretty important later on. 😉

Datatables

And here is the view code.

@using Nancy
<!DOCTYPE html>

<html>
<head>
    <title>Plants</title>
    <link href="@Url.Content("~/Content/themes/smoothness/jquery-ui.css")" rel="stylesheet" />
    <link href="@Url.Content("~/Content/themes/smoothness/jquery.ui.theme.css")" rel="stylesheet" />
    <link href="@Url.Content("~/Content/DataTables-1.9.4/media/css/jquery.dataTables_themeroller.css")" rel="stylesheet" />
    <script src="@Url.Content("~/Content/Scripts/jquery-1.9.0.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Content/Scripts/jquery-ui-1.10.0.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Content/Scripts/DataTables-1.9.4/media/js/jquery.dataTables.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Content/Scripts/DataTables-1.9.4/media/js/jquery.dataTables.ColumnResizeAndReorder.js")"></script><script type="text/javascript">
        $(document).ready(function () {
            $('#table_id').dataTable({
                "bProcessing": true,
                "bStateSave": true,
                "bServerSide": true,
                "bJQueryUI": true,
                "bFilter": false,
                "sAjaxSource": "/plants",
                "sDom": 'R<"dataTables_HeaderWrapper"<"H"lfr>><"dataTables_BodyWrapper"t><"dataTables_FooterWrapper"<"F"ip>>',
                "aoColumns": [
                    { "mData": "Id", "sTitle": "Id", "sWidth": "20%", "bSortable": true },
                    { "mData": "Name", "sTitle": "Name", "sWidth": "40%", "bSortable": false },
                    { "mData": "Genus", "sTitle": "Genus1", "sWidth": "40%", "bSortable": false }
                ],
                "sPaginationType": "full_numbers",
                "fnServerData": function (sSource, aoData, fnCallback) {
                    $.getJSON(sSource, aoData, function (jsondata) {
                        fnCallback(jsondata);
                    });
                }
            });
        });
    </script>
</head>
<body>
    <table id="table_id">
        <thead>
            <tr>
                <th>Id</th>
                <th>Name</th>
                <th>Genus</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td colspan="3" class="dataTables_empty">Loading data from server</td>
            </tr>
        </tbody>
    </table>
    <div id="dataoutput"></div>
</body>
</html>

I also have a plugin to resize the columns because that is not something that is builtin with datatables. You can find that plugin on the extras page of the datatables website.

It is important that we use mData for our columns for because we use objectnotation in our json. The fnServerData has the function that gets our json data.

Look at the html. You need a lot more html than most other frameworks. But it works. Well not actually sure you need that much html because this is one of the parts where the docs are a bit lacking.

It was also lacking on which libraries to import (js and css) but you now have all of them in the code above.

And this is the result.

Conclusion

Is datatables better than jtable? Pff, nah. But I can use a Get instead of a Post to get my data and that is an improvement.