Wednesday, 30 March 2016

Kendo Grid in Action

Introduction
If we want to present or work with tabular data in our web application then we have to use HTML table or other libraries (grid) like easyUI, Kendo UI, DataTables, jqGrid, extJS etc. I found Kendo UI Grid is easy and more maintainable.
Here I am going to write some basic usage of kendo UI Grid control which is used to work with tabular data. After reading my post reader will able to use kendo UI grid on their application. Finally I will use kendo UI Grid on my ASP.net MVC 4 project to manipulate tabular data and also show how to post list of data from view to controller so that it helps reader to work with master detail record on their web application.

Kendo Grid in Action
>Now a question may come on your mind right!
If documentation and demos are available on Kendo UI Site then why I am writing about Kendo grid?
Let’s try to answer above question. Actually I am creating a summary note which includes most common operations performed on grid/ table. If you decide; you will use kendo grid then you will look for some basic operations right? But it is difficult to find common operations altogether from Kendo documentation. So here I have tried to show some common operations performed on grid/table altogether so that reader can get required knowledge to work with kendo grid on their web project.
Background
Kendo UI is jQuery-based widgets. Kendo
UI also support server side wrapping (commercial version only) but in my post I
will describe only client side issues because Kendo UI web is free for client side using.
Kendo UI something like jQuery UI but this is richer than jQuery UI. If you are
interested then you can check a comparison (jQuery UI vs Kendo UI) between them.
Let’s move to Kendo UI Grid. A full
documentation about Kendo UI Grid available on http://docs.kendoui.com/api/web/grid.
Where we use grid/table
Let’s try to find some issues where we use grid/Table.
  1. We use html table for showing static tabular data in our application.• Problem & Solution: In case of simple html table we have to think separately for paging, filtering and so on. If we use Kendo Grid then we don’t need to think about paging, column filtering and so on.
  2. We use html table for showing filtered data (dynamically changed data).• Problem & Solution: In that case we have to redraw html table after each filtering. We cannot bind JSON data directly with html table. Kendo Grid gives us option to bind JSON data with table dynamically.
  3. We use html table to collect list of information from user.• Problem & Solution: When we collect information from user then we append new row with existing table and when user need to remove any item then we delete desired row from existing table. In this case we have to write some JS/jQuery code to perform these operations but Kendo Grid gives us easy interface; from where we can easily add new row by giving only JSON data.
  4. Sometimes we need to extract selected row’s data from html table.• Problem & Solution: In that case we collect our desired data as a table row and from there we have to parse specific data. We cannot get data as a JSON object but kendo grid gives selected data as a JSON object.
  5. And so on….
In this post I will try to perform above operations using Kendo Grid.
So finally what I will show…..? Let’s make a list.
  • Applying Kendo Grid on existing HTML Table
  • Paging, sorting, filtering using Kendo Grid
  • Resizing Kendo Grid
  • Creating grid from JSON Data
  • Rebind Kendo Grid with JSON Data
  • Adding new row to Grid
  • Getting selected row’s data
  • Removing row/record from Kendo Grid
  • Iterate through all rows
  • Hide column from Kendo Grid
  • Creating template column on Kendo Grid
  • Adding double click event on Kendo Grid
  • Adding row change event on Kendo Grid
  • Checkbox column in Kendo Grid
  • Posting List of data from UI to Server side
Before Starting with Kendo Grid.
1. Download Kendo UI Web from http://www.kendoui.com/download.aspx
OR
If you are using Visual Studio then you can use nuget to add Kendo UI Web on your project
OR
Use “Install-Package KendoUIWeb” from Package Manager Console
2. Kendo UI is dependent on jQuery so add reference of jQuery on your project.
Finally you have to add following references on your page/ site.
?
1
2
3
4
5
6
7
8
9
<!--<span class="code-comment"> Add CSS reference --></span>
<link href="~/Content/kendo/2012.3.1114/kendo.common.min.css" rel="stylesheet" />

<!--<span class="code-comment"> CSS reference for theme; you can make custom them from http://demos.kendoui.com/themebuilder/web.html --></span>
<link href="~/Content/kendo/2012.3.1114/kendo.metro.min.css" rel="stylesheet" />

<!--<span class="code-comment"> Add JS Script reference --></span>
<script src="~/Scripts/jquery-1.8.3.min.js"></script>
<script src="~/Scripts/kendo/2012.3.1114/kendo.web.min.js"></script>
Kendo Grid in Action
In this section I will show some example of using kendo Grid so that we can solve above problems.
A Complete Demo http://jsbin.com/iwagez/1/
Applying Kendo Grid on existing HTML Table
We can easily apply kendo grid on html table by following way.
?
1
2
3
$(document).ready(function(){
    $('#grid').kendoGrid();
});
Here grid is a table id.
Paging, sorting, filtering using Kendo Grid
To enable paging, sorting and filtering we just need to make them true when kendo grid initialization.
?
1
2
3
4
5
6
7
8
$('#grid').kendoGrid({
    scrollable: true,
    sortable: true,
    pageable: true,
    selectable: "row",
    filterable: true
  , dataSource: { pageSize: 10 }     //defining page size     
});
Resizing Kendo Grid
We are applying kendo grid on dib or table. We can define width in following way
?
1
<div id="grid" class="k-content" style="width: 450Px"></div>
For defining height we have to use kendoGrid Initialization. Consider following way
?
1
2
3
4
$(document).ready(function ()
            {
                $('#grid').kendoGrid({ , height: 350 //350 equals 350Px });
            });
Creating grid from JSON Data
Following code shows how we can bind JSON data with kendo grid.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$(document).ready(function () {
//JSON data
var people = [
{ firstName: "Hasibul", lastName: "Haque", email: "hasibul2363@gmail.com" }
, { firstName: "Jane", lastName: "Smith", email: "jane.smith@kendoui.com" }
];

$('#grid').kendoGrid({
scrollable: true,
sortable: true,
pageable: true,
selectable: "row",
filterable: true

, dataSource: { data: people, pageSize: 10 } //binding JSON data with grid

});

});
Rebind Kendo Grid with JSON Data
If we want to rebind our grid with another json data then we can apply following way.
?
1
2
3
4
5
6
//Selecting existing grid
var vgrid = $("#grid").data("kendoGrid");
var datasource = vgrid.dataSource;
var newSource = { firstName: "Ruhan", lastName: "Ruhan", email: "ruhan@kendoui.com" };
//Applying new source
datasource.data(newSource);
Adding new row to Kendo Grid
?
1
2
3
4
5
6
7
//Selecting Grid
var vgrid = $("#grid").data("kendoGrid");
//Selecting dataSource
var datasource = vgrid.dataSource;
var newRecord = { firstName: "Hasibul", lastName: "Haque", email: "hasibul@kendoui.com" };
//Inserting new row
datasource.insert(newRecord);
Getting selected row’s data from Kendo Grid
?
1
2
3
4
5
6
//Selecting Grid
var gview = $("#grid").data("kendoGrid");
//Getting selected item
var selectedItem = gview.dataItem(gview.select());
//accessing selected rows data
alert(selectedItem.email);
Getting multiple selected rows data
?
1
2
3
4
5
6
7
8
9
//Selecting Grid
var gview = $("#grid").data("kendoGrid");
//Getting selected rows
var rows = entityGrid.select();
//Iterate through all selected rows
rows.each(function (index, row) {
var selectedItem = gview.dataItem(row);
// your action will go here
});
Removing row/record from Kendo Grid
?
1
2
3
4
5
6
7
8
//Selecting Grid
var gview = $("#grid").data("kendoGrid");
//Getting selected row
var dataItem = gview.dataItem(gview.select());
//Removing Selected row
gview.dataSource.remove(dataItem);
//Removing row using index number
gview.dataSource.remove(0);// 0 is row index
Iterate through all rows
?
1
2
3
4
5
6
7
8
//Selecting Grid
var vgrid = $("#grid").data("kendoGrid");
//Getting grid items
var items = vgrid.dataSource.data();
for (i = 0; i < items.length; i++) {
var item = items[i];
alert(item.firstName);
}
Hide column from Kendo Grid
?
1
2
3
4
5
6
var grid = $("#grid").data("kendoGrid");
// hide by column name
grid.hideColumn("id");

// hide column by index
grid.hideColumn(2);
Creating template column in Kendo Grid

Template column in kendo Grid
In action column I don’t want to show any data but want to show a link; when user click on it then he will be navigated to another page but for making link; I may need another columns value. Using syntax #=fieldname# we can access another column value. Kendo UI uses #= # syntax to write template code.
Consider following code for making kendo grid with template column
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$('#grid').kendoGrid({
scrollable: true,
sortable: true,
pageable: true,
selectable: "row",
filterable: true
, dataSource: { data: people, pageSize: 10 }
, columns:
[
{ field: "firstName", title: "First Name" }
, { field: "lastName", title: "Last Name" }
, { field: "email", title: "email" }
, {
title: "Action",
template: "<a href='http://www.codeproject.com/foo?firstName=#=firstName#'>Edit</a>"
, filterable: false
}
]
});
Or you can check live demo http://jsbin.com/erahat/7/
Adding double click event on Kendo Grid
We have to add a class name on our table called “k-content”. Then we will apply double click event on “k-content”.
?
1
$(".k-content").dblclick(function(){//Your code will go here});
You can check it from live demo link
Adding selected row change Event on Kendo Grid
We can add selected row change event in following way
?
1
2
var grid = $("#grid").data("kendoGrid");
grid.bind("change", RowSelectionChangeEvent);
A Complete Demo http://jsbin.com/iwagez/1/
Checkbox column in Kendo Grid

Check box column in kendo Grid
Fig: Showing Boolean data using check box column.
Consider we have JSON data and one of attribute is Boolean. We can easily present Boolean data using check box. Let’s see how we can present Boolean data using checkbox column in Kendo Grid. Later we will dig more.
Consider following code for making kendo grid with checkbox column template.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script type="text/javascript">

$(document).ready(function () {
var users = [{ UserId: 1, UserName: "Robin", IsAdmin: true }
, { UserId: 2, UserName: "Hood", IsAdmin: false }];

$("#grid").kendoGrid({
dataSource: { data: users, pageSize: 10 }// binding data
,pageable: true
, selectable: "multiple row"
, columns: [
{ field: "UserId" }
, { field: "UserName" }
// Creating template column
, { field: "IsAdmin", title: "Is Admin", template: "<input type=\"checkbox\" #= IsAdmin ? checked='checked' : '' # class=\"check_row\"/>" }
]
});
});
</script>
<div id="grid"></div>
Here I just created template column for showing Boolean data. If you edit that means if you check or uncheck any column then it doesn’t affect data item. So you cannot get updated record when iterate through grid data.
So I have to add click event on check box (class name= check_row) so that user action update the data item. Let’s see how we can do this.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Adding click event on check box
$('.check_row').live('click', function (e) {
//Getting checkbox
var $cb = $(this);
//Getting checkbox value
var checked = $cb.is(':checked');
//Setting checkbox value to data Item
setValueToGridData(checked);
});

function setValueToGridData(val) {
//Selecting Grid
var grid = $("#grid").data("kendoGrid");
//Getting selected Item(s)
var selectedItems = grid.select();
selectedItems.each(function (index, row) {
var selectedItem = grid.dataItem(row);
//Setting value to data item; so that we can read updated data
selectedItem.set('IsAdmin', val);

});
If we iterate through table data then we will get desire data according to user selection on checkbox column.
You can check from live demo
Now what we are missing?? A header with check box; which will select or deselect all rows, right? Let’s see how we can add check box on column header and also see how we can add event on header check box which will change the checkbox status and also change grid rows data.
First we have to add header template like following
headerTemplate: '<label> <input type="checkbox" id="checkAll"/>Check</label>'
Then we have to add click event on header checkbox like following
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$("#checkAll").live('click', function (e) {

var $cb = $(this);
var checked = $cb.is(':checked');
var grid = $('#grid').data('kendoGrid');
grid.table.find("tr").find("td:last input").attr("checked", checked);

//now making all the rows value to true or false
var items = $("#grid").data("kendoGrid").dataSource.data();
for (i = 0; i < items.length; i++) {
var item = items[i];
item.set(IsAdmib, checked);

}

//If checkbox is unchecked them clear all rows
if (!checked)
{
$("#grid").data("kendoGrid").clearSelection();
}

});
Now what we are missing????
> We want our row to be highlighted when we select a check box. If we check header check box then all row will be highlighted.
How we can achieve above let’s see
Before doing above I want to share 2 problems
  1. Selection of row(s) lose when I navigate to another page.
  2. If I check header check box then it should check all rows but it selects only selected page’s rows.

Solution
  1. We have to implement a mechanism so that it can memorize every selection when we navigate to another page.
  2. If we apply Selected Row CSS by reading current page’s row then all rows of the table will not be affected. So we have to apply changes on data instead of table row.
Now let’s do….
> Let’s highlight the row when user check the check box. Here we have to add change event on check box so that we can apply CSS for individual row. Here I am adding dataBound event on kendo grid. Inside this event I am adding checkbox change event.
Please check following.

 Fig: Kendo Grid with Checkbox column with multiple select
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
dataBound: function() {
            var grid = this;           
                //handle checkbox change event
                grid.table.find("tr").find("td:last input")
                    .change(function(e) {

                        var checkbox = $(this);
                        var selected = grid.table.find("tr").find("td:last input:checked").closest("tr");

                        grid.clearSelection();

                        //persist selection per page;
                        var ids = selectedIds[grid.dataSource.page()] = [];

                        if (selected.length) {
                            grid.select(selected);
                            selected.each(function(idx, item) {
                               //Adding ids to buffer so that it can memorize the changes
                                ids.push($(item).data("uid"));
                            });
                        }

                    });

                //select persisted rows
                var ids = selectedIds[grid.dataSource.page()] || [];

               //Adding css to buffered rows
                for (var idx = 0, length = ids.length; idx < length; idx++) {
                    var tr = grid.tbody.find("tr[data-uid='" + ids[idx] + "']");
                    tr.addClass("k-state-selected");
                    tr.find("td:last input").attr("checked", checked);
                }

                //If header is checked then make all rows selected
                if($("#checkAll").is(':checked') == true)
                {
                    $('#grid').data('kendoGrid').tbody.find("tr").addClass('k-state-selected');
                    $('#grid').data('kendoGrid').tbody.find("tr").find("td:last input").attr("checked", checked);
                }

  // Outside of change event; it will fire on page change
                //if check box is checked then adding css to checked row
                grid.table.find("tr").find("td:last input:checked").closest("tr").addClass('k-state-selected');

        }
Posting List of data from UI to Server side
Here I will try to show how to post list of data to server side so that it helps beginner to work with master detail record. Here I am using ASP.net MVC 4 for making sample solution.
Consider I have “User” entity like following
?
1
2
3
4
5
6
7
public class User
{
        public int UserId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
}
Now consider I have a view which consist of list of user like following image
Fig: List of User inside kendo grid
Now I want to post this grid data (list of user) to server side. If we use html table then we have to parse table row to get desire data. Kendo grid helps us to get JSON data without parsing. We can get JSON data just writing following code.
?
1
var users = $("#gridUser").data("kendoGrid").dataSource.data();
Now we have JSON data and we can easily post this to server.
Consider we have a controller method like following
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        [HttpPost]
public JsonResult SaveGridData(List<user> users)
{
    // Here I am not implementing all
    // I am interested to show controller is getting data from view
    var count = 0;
    if (users != null)
    {
        count = users.Count;
    }
    //Returns how many records was posted
    return Json(new { count = count });
}

</user>
Let’s send view data to controller using ajax post
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
            function Save() {
//getting json data from kendo Grid
        var gridData = $("#gridUser").data("kendoGrid").dataSource.data();
        $.ajax({
            type: "POST"
            , url: "/Home/SaveGridData"
            , data: JSON.stringify({ users: gridData })
            ,contentType:"application/json"
            , success: function (result) {
                alert(result.count+ " record(s) found");
            }
        });

    }
If I run my solution in debugging mode then I will find 2 records are posted to server side like following

Fig: After posting view data (list of user) to controller.
Conclusion
I think these are the basic operations for any simple project where we need to work with table/grid. Here I have tried to show some simple usage of kendo grid so that people can play with it and get necessary things altogether.
Hope you enjoyed the simplicity of Kendo UI Grid.

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...