jTable.org

A JQuery plugin to create AJAX based CRUD tables.

Demos | Documentation | Discussion | Themes | Downloads | About
jTable on GitHub Github


HTML code

<div id="StudentTableContainer"></div>

Javascript code

<script type="text/javascript">
    
    var cachedCityOptions = null;
    
    $(document).ready(function () {
        $('#StudentTableContainer').jtable({
            title: 'Student List',
            paging: true,
            pageSize: 10,
            sorting: true,
            multiSorting: true,
            defaultSorting: 'Name ASC',
            actions: {
                listAction: function (postData, jtParams) {
                    console.log("Loading from custom function...");
                    return $.Deferred(function ($dfd) {
                        $.ajax({
                            url: '/Demo/StudentList?jtStartIndex=' + jtParams.jtStartIndex + '&jtPageSize=' + jtParams.jtPageSize + '&jtSorting=' + jtParams.jtSorting,
                            type: 'POST',
                            dataType: 'json',
                            data: postData,
                            success: function (data) {
                                $dfd.resolve(data);
                            },
                            error: function () {
                                $dfd.reject();
                            }
                        });
                    });
                },
                deleteAction: function (postData) {
                    console.log("deleting from custom function...");
                    return $.Deferred(function ($dfd) {
                        $.ajax({
                            url: '/Demo/DeleteStudent',
                            type: 'POST',
                            dataType: 'json',
                            data: postData,
                            success: function (data) {
                                $dfd.resolve(data);
                            },
                            error: function () {
                                $dfd.reject();
                            }
                        });
                    });
                },
                createAction: function (postData) {
                    console.log("creating from custom function...");
                    return $.Deferred(function ($dfd) {
                        $.ajax({
                            url: '/Demo/CreateStudent',
                            type: 'POST',
                            dataType: 'json',
                            data: postData,
                            success: function (data) {
                                $dfd.resolve(data);
                            },
                            error: function () {
                                $dfd.reject();
                            }
                        });
                    });
                },
                updateAction: function(postData) {
                    console.log("updating from custom function...");
                    return $.Deferred(function ($dfd) {
                        $.ajax({
                            url: '/Demo/UpdateStudent',
                            type: 'POST',
                            dataType: 'json',
                            data: postData,
                            success: function (data) {
                                $dfd.resolve(data);
                            },
                            error: function () {
                                $dfd.reject();
                            }
                        });
                    });
                }
            },
            fields: {
                StudentId: {
                    key: true,
                    create: false,
                    edit: false,
                    list: false
                },
                Name: {
                    title: 'Name',
                    width: '23%'
                },
                EmailAddress: {
                    title: 'Email address',
                    list: false
                },
                Password: {
                    title: 'User Password',
                    type: 'password',
                    list: false
                },
                Gender: {
                    title: 'Gender',
                    width: '13%',
                    options: { 'M': 'Male', 'F': 'Female' }
                },
                CityId: {
                    title: 'City',
                    width: '12%',
                    options: function () {
                        
                        if (cachedCityOptions) { //Check for cache
                            return cachedCityOptions;
                        }

                        var options = [];

                        $.ajax({ //Not found in cache, get from server
                            url: '/Demo/GetCityOptions',
                            type: 'POST',
                            dataType: 'json',
                            async: false,
                            success: function (data) {
                                if (data.Result != 'OK') {
                                    alert(data.Message);
                                    return;
                                }
                                options = data.Options;
                            }
                        });
                        
                        return cachedCityOptions = options; //Cache results and return options
                    }
                },
                BirthDate: {
                    title: 'Birth date',
                    width: '15%',
                    type: 'date',
                    displayFormat: 'yy-mm-dd'
                },
                Education: {
                    title: 'Education',
                    list: false,
                    type: 'radiobutton',
                    options: { '1': 'Primary school', '2': 'High school', '3': 'University' }
                },
                About: {
                    title: 'About this person',
                    type: 'textarea',
                    list: false
                },
                IsActive: {
                    title: 'Status',
                    width: '12%',
                    type: 'checkbox',
                    values: { 'false': 'Passive', 'true': 'Active' },
                    defaultValue: 'true'
                },
                RecordDate: {
                    title: 'Record date',
                    width: '15%',
                    type: 'date',
                    displayFormat: 'yy-mm-dd',
                    create: false,
                    edit: false,
                    sorting: false //This column is not sortable!
                }
            }
        });
        //Load student list from server
        $('#StudentTableContainer').jtable('load');
    });
</script>

Server side code

public class DemoController : Controller
{
    //...

    [HttpPost]
    public JsonResult StudentList(int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = null)
    {
        try
        {
            //Get data from database
            int studentCount = _repository.StudentRepository.GetStudentCount();
            List<Student> students = _repository.StudentRepository.GetStudents(jtStartIndex, jtPageSize, jtSorting);

            //Return result to jTable
            return Json(new { Result = "OK", Records = students, TotalRecordCount = studentCount });
        }
        catch (Exception ex)
        {
            return Json(new { Result = "ERROR", Message = ex.Message });
        }
    }

    [HttpPost]
    public JsonResult CreateStudent(Student student)
    {
        try
        {
            if (!ModelState.IsValid)
            {
                return Json(new { Result = "ERROR", Message = "Form is not valid! Please correct it and try again." });
            }

            Student addedStudent = _repository.StudentRepository.AddStudent(student);
            return Json(new { Result = "OK", Record = addedStudent });
        }
        catch (Exception ex)
        {
            return Json(new { Result = "ERROR", Message = ex.Message });
        }
    }

    [HttpPost]
    public JsonResult UpdateStudent(Student student)
    {
        try
        {
            if (!ModelState.IsValid)
            {
                return Json(new { Result = "ERROR", Message = "Form is not valid! Please correct it and try again." });
            }

            _repository.StudentRepository.UpdateStudent(student);
            return Json(new { Result = "OK" });
        }
        catch (Exception ex)
        {
            return Json(new { Result = "ERROR", Message = ex.Message });
        }
    }

    [HttpPost]
    public JsonResult DeleteStudent(int studentId)
    {
        try
        {
            _repository.StudentRepository.DeleteStudent(studentId);
            return Json(new { Result = "OK" });
        }
        catch (Exception ex)
        {
            return Json(new { Result = "ERROR", Message = ex.Message });
        }
    }

    [HttpPost]
    public JsonResult GetCityOptions()
    {
        try
        {
            var cities = _repository.CityRepository.GetAllCities().Select(c => new { DisplayText = c.CityName, Value = c.CityId });
            return Json(new { Result = "OK", Options = cities });
        }
        catch (Exception ex)
        {
            return Json(new { Result = "ERROR", Message = ex.Message });
        }
    }
}

See "Using jTable with ASP.NET MVC" tutorial for detailed usage.
Download all samples from download page.

public partial class PagingAndSorting : System.Web.UI.Page
{
    //...

    [WebMethod(EnableSession = true)]
    public static object StudentList(int jtStartIndex, int jtPageSize, string jtSorting)
    {
        try
        {
            //Get data from database
            int studentCount = _repository.StudentRepository.GetStudentCount();
            List<Student> students = _repository.StudentRepository.GetStudents(jtStartIndex, jtPageSize, jtSorting);

            //Return result to jTable
            return new { Result = "OK", Records = students, TotalRecordCount = studentCount };
        }
        catch (Exception ex)
        {
            return new { Result = "ERROR", Message = ex.Message };
        }
    }

    [WebMethod(EnableSession = true)]
    public static object CreateStudent(Student record)
    {
        try
        {
            var addedStudent = _repository.StudentRepository.AddStudent(record);
            return new { Result = "OK", Record = addedStudent };
        }
        catch (Exception ex)
        {
            return new { Result = "ERROR", Message = ex.Message };
        }
    }

    [WebMethod(EnableSession = true)]
    public static object UpdateStudent(Student record)
    {
        try
        {
            _repository.StudentRepository.UpdateStudent(record);
            return new { Result = "OK" };
        }
        catch (Exception ex)
        {
            return new { Result = "ERROR", Message = ex.Message };
        }
    }

    [WebMethod(EnableSession = true)]
    public static object DeleteStudent(int StudentId)
    {
        try
        {
            _repository.StudentRepository.DeleteStudent(StudentId);
            return new { Result = "OK" };
        }
        catch (Exception ex)
        {
            return new { Result = "ERROR", Message = ex.Message };
        }
    }

    [WebMethod(EnableSession = true)]
    public static object GetCityOptions()
    {
        try
        {
            var cities = _repository.CityRepository.GetAllCities().Select(c => new { DisplayText = c.CityName, Value = c.CityId });
            return new { Result = "OK", Options = cities };
        }
        catch (Exception ex)
        {
            return new { Result = "ERROR", Message = ex.Message };
        }
    }
}

See "Using jTable with ASP.NET Web Forms" tutorial for detailed usage.
Download all samples from download page.

This demo is for demonstrating using functions as actions. For simply Paging&Sorting, see Paging&Sorting demo.

By using your own custom functions to communicate with server, you can implement your own protocols that works fine with jTable. To do this, you can set your functions as listAction, updateAction, createAction, deleteAction in jTable definition code as shown in this demo.

A function (that is set as action) can either return the data jTable needs or can return a promise using jQuery.Deffered object (as implemented in this demo) to return data later. Data must be formatted as described in documentations. If your server returns data formatted different than jTable expects, you must convert to jTable format in your function.

In this demo, there is also shown to get data from server in "options" for a combobox field. Notice that, the data is cached! This is very important since this function is called for each record on the table. If returning options are not cached, a seperated ajax request made for each record on the table. This would be a major performance problem. Also ajax request (while getting options from server) must be synchronous (see async: false in ajax call) since this function must return options at the end of the method (not like actions implemented using jQuery.Deferred).

Advertisement: Professional startup template for ASP.NET MVC & AngularJs by creator of jTable!

ASP.NET Zero screenshot Based on metronic theme, includes pre-built pages like login, register, tenant, role, user, permission and setting management. Learn more...