jTable.org

A JQuery plugin to create AJAX based CRUD tables.

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

How it works

jTable allows you to easily create cascade drop downs on edit/create forms without using any other library. To see demo, try to edit a row on table or add a new record to the table. You see that Continental, Country and City comboboxes are cascaded.

To achive cascading, you must use dependsOn and options field options as used as this demo. Then, jTable automatically cascades comboboxes.

HTML code

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

Javascript code

<script type="text/javascript">

    $(document).ready(function () {

        $('#StudentTableContainer').jtable({
            title: 'Student List',
            paging: true,
            pageSize: 10,
            sorting: true,
            defaultSorting: 'Name ASC',
            actions: {
                listAction: '/Demo/StudentList',
                deleteAction: '/Demo/DeleteStudent',
                updateAction: '/Demo/UpdateStudent',
                createAction: '/Demo/CreateStudent'
            },
            fields: {
                StudentId: {
                    key: true,
                    create: false,
                    edit: false,
                    list: false
                },
                Name: {
                    title: 'Name',
                    width: '30%'
                },
                EmailAddress: {
                    title: 'Email address',
                    list: false
                },
                Password: {
                    title: 'User Password',
                    type: 'password',
                    list: false
                },
                Gender: {
                    title: 'Gender',
                    options: { 'M': 'Male', 'F': 'Female' },
                    list: false
                },
                ContinentalId: {
                    title: 'Continental',
                    options: '/Demo/GetContinentalOptions',
                    list: false
                },
                CountryId: {
                    title: 'Country',
                    dependsOn: 'ContinentalId', //Countries depends on continentals. Thus, jTable builds cascade dropdowns!
                    options: function (data) {
                        if (data.source == 'list') {
                            //Return url of all countries for optimization. 
                            //This method is called for each row on the table and jTable caches options based on this url.
                            return '/Demo/GetCountryOptions?continentalId=0';
                        }

                        //This code runs when user opens edit/create form or changes continental combobox on an edit/create form.
                        //data.source == 'edit' || data.source == 'create'
                        return '/Demo/GetCountryOptions?continentalId=' + data.dependedValues.ContinentalId;
                    },
                    list: false
                },
                CityId: {
                    title: 'City',
                    width: '30%',
                    dependsOn: 'CountryId', //Cities depends on countries. Thus, jTable builds cascade dropdowns!
                    options: function (data) {
                        if (data.source == 'list') {
                            //Return url of all cities for optimization. 
                            //This method is called for each row on the table and jTable caches options based on this url.
                            return '/Demo/GetCityOptions?countryId=0';
                        }

                        //This code runs when user opens edit/create form or changes country combobox on an edit/create form.
                        //data.source == 'edit' || data.source == 'create'
                        return '/Demo/GetCityOptions?countryId=' + data.dependedValues.CountryId;
                    }
                },
                BirthDate: {
                    title: 'Birth date',
                    type: 'date',
                    displayFormat: 'yy-mm-dd',
                    list: false
                },
                Education: {
                    title: 'Education',
                    list: false,
                    type: 'radiobutton',
                    options: [
                        { Value: '1', DisplayText: 'Primary school' },
                        { Value: '2', DisplayText: 'High school' },
                        { Value: '3', DisplayText: 'University' }
                    ]
                },
                About: {
                    title: 'About this person',
                    type: 'textarea',
                    list: false
                },
                IsActive: {
                    title: 'Status',
                    width: '15%',
                    type: 'checkbox',
                    values: { 'false': 'Passive', 'true': 'Active' },
                    defaultValue: 'true'
                },
                RecordDate: {
                    title: 'Record date',
                    width: '25%',
                    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 GetContinentalOptions()
	{
		try
		{
			var continentals = _repository.ContinentalRepository.GetAllContinentals().Select(c => new { DisplayText = c.ContinentalName, Value = c.ContinentalId }).OrderBy(s => s.DisplayText);
			return Json(new { Result = "OK", Options = continentals });
		}
		catch (Exception ex)
		{
			return Json(new { Result = "ERROR", Message = ex.Message });
		}
	}

	[HttpPost]
	public JsonResult GetCountryOptions(int continentalId = 0)
	{
		try
		{
			var countries = _repository.CountryRepository.GetAllCountries(continentalId).Select(c => new { DisplayText = c.CountryName, Value = c.CountryId }).OrderBy(s => s.DisplayText);
			return Json(new { Result = "OK", Options = countries });
		}
		catch (Exception ex)
		{
			return Json(new { Result = "ERROR", Message = ex.Message });
		}
	}

	[HttpPost]
	public JsonResult GetCityOptions(int countryId = 0)
	{
		try
		{
			var cities = _repository.CityRepository.GetAllCities(countryId).Select(c => new { DisplayText = c.CityName, Value = c.CityId }).OrderBy(s => s.DisplayText);
			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 Cascaded : 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 GetContinentalOptions()
	{
		try
		{
			var continentals = _repository.ContinentalRepository.GetAllContinentals().Select(c => new { DisplayText = c.ContinentalName, Value = c.ContinentalId }).OrderBy(s => s.DisplayText);
			return new { Result = "OK", Options = continentals };
		}
		catch (Exception ex)
		{
			return new { Result = "ERROR", Message = ex.Message };
		}
	}	
	
	[WebMethod(EnableSession = true)]
	public static object GetCountryOptions(int continentalId)
	{
		try
		{
			var countries = _repository.CountryRepository.GetAllCountries(continentalId).Select(c => new { DisplayText = c.CountryName, Value = c.CountryId }).OrderBy(s => s.DisplayText);
			return new { Result = "OK", Options = countries };
		}
		catch (Exception ex)
		{
			return new { Result = "ERROR", Message = ex.Message };
		}
	}

    [WebMethod(EnableSession = true)]
    public static object GetCityOptions(int countryId)
    {
        try
        {
            var cities = _repository.CityRepository.GetAllCities(countryId).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.

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...