I need to set Kendo grid action button Icon based on value. My code as follows,
function InitProductServicesGrid() {
var prodServiceDataSource = new kendo.data.DataSource({
transport: {
type: "json",
read:
{
url: SERVER_PATH + "/LTSService/ProductsService.asmx/GetProductServiceDetailsList",
type: "POST",
contentType: 'application/json',
data: GetAdditonalData,
datatype: "json"
},
update:
{
url: SERVER_PATH + "/LTSService/ProductsService.asmx/SaveProductService",
type: "POST",
contentType: 'application/json',
datatype: "json"
}
},
schema: {
data: function (result) {
return JSON.parse(result.d);
},
model: {
id: "Id",
fields: {
Id: { type: "int" },
ServiceTime: { type: "string" },
IsActive: { type: "boolean"}
}
}
},
requestEnd: function (e) {
if (e.type === "destroy") {
var grid = $("#productServicesGrid").data("kendoGrid");
grid.dataSource.read();
}
},
error: function (e) {
e.preventDefault();
if (e.xhr !== undefined && e.xhr !== null) {
var messageBody = e.xhr.responseJSON.Message;
ShowGritterMessage("Errors", messageBody, false, '../App_Themes/Default/LtsImages/errorMessageIcon_large.png');
var grid = $("#productServicesGrid").data("kendoGrid");
grid.cancelChanges();
}
},
pageSize: 20,
});
$("#productServicesGrid").kendoGrid({
dataSource: prodServiceDataSource,
sortable: true,
filterable: false,
pageable: true,
dataBound: gridDataBound,
editable: {
mode: "inline",
confirmation: false
},
columns: [
{ field: "Id", title: "", hidden: true },
{
field: "ServiceTime",
title: "Time Standard",
sortable: false,
editor: function (container, options) {
var serviceTimeTxtBox = RenderServiceTime();
$(serviceTimeTxtBox).appendTo(container);
},
headerTemplate: '<a class="k-link" href="#" title="Time Standard">Time Standard</a>'
},
{
title: "Action", command: [
{
name: "hideRow",
click: hideRow,
template: comandTemplate
}
],
width: "150px"
}
]
});
}
I wrote a custom template function as follows,
function comandTemplate(model) {
if (model.IsActive == true) {
return '<a title="Hide" class="k-grid-hideRow k-button"><span class="k-icon k-i-lock"></span></a><a title="Hide"></a>';
}
else {
return '<a title="Show" class="k-grid-hideRow k-button"><span class="k-icon k-i-unlock"></span></a><a title="Show"></a>';
}
}
But when I debug the I saw the following value for model value.
I followed this sample code as well. here you can see, I also set the custom template like the sample code. Please help me to solve this. Why I can't access model IsActive value from comandTemplate function.
Updated
When clicking hideRow action, I access the dataItem as follows.
function hideRow(e) {
e.preventDefault();
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
if (dataItem.IsActive == true) {
dataItem.IsActive = false;
}
else {
dataItem.IsActive = true;
}
}
Is there any possible way to access data from template function as above or any other way?
I would suggest a different approach because you can't access grid data while rendering and populating grid.
My suggestion is to use two actions and hide it based on the flag (in your case IsActive).
Something like this: Custom command
NOTE: in visible function you can access item!
EDIT: you can access it and change it on dataBound traversing through all data.
Check this example: Data bound
I don't see the advantage of relying on the grid commands. You can render any button you want yourself and and use the dataBound event to bind a click handler:
$("#grid").kendoGrid({
columns: [
{ field: "name" },
{
template: function(dataItem) {
const isActive = dataItem.isActive;
return `<a title=${isActive ? "Hide": "Show"} class="k-grid-hideRow k-button"><span class="k-icon k-i-${isActive ? 'lock' : 'unlock'}"></span></a>`
}
}
],
dataBound: function(e) {
e.sender.tbody.find(".k-grid-hideRow").click(evt => {
const row = evt.target.closest("tr")
const dataItem = e.sender.dataItem(row)
dataItem.set("isActive", !dataItem.isActive)
})
},
dataSource: [{ name: "Jane Doe", isActive: false }, { name: "Jane Doe", isActive: true }]
});
Runnable Dojo: https://dojo.telerik.com/#GaloisGirl/eTiyeCiJ
Related
I am using the treeview and HierarchicalDataSource of KendoUI. Plus on the top I also had a kendoDropDownList. Basically each time user change the dropdownlist value it trigger change event and HierarchicalDataSource will read again. But seem my dropdown change event not working as i expected? I did not call HierarchicalDataSource.read(). Any idea what I doing wrong?
Dropdownlist
$("#dropdown").kendoDropDownList({
dataTextField: "functionName",
dataValueField: "hrsPositionID",
dataSource: {
transport:{
read: {
url: "./getDropdown.php",
type: "POST",
data: function() {
return {
method: "getDropdown",
}
}
},
},
},
change: function(e){
console.log(this.value());
$('#AccountingTree').data('kendoTreeView').HierarchicalDataSource.read(); //<-- not working
}
}).data('kendoDropDownList');
dropdownlist = $("#dropdown").data("kendoDropDownList");
HierarchicalDataSource & kendoTreeView
var serviceRoot = "./getyzdTreeView.php";
dataSource = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: serviceRoot,
dataType: "json",
type: "POST",
data: function(){
return {
positionID: dropdownlist.value() //read the value from dropdownlist
}
}
}
},
schema: {
model: {
id : "programID",
hasChildren: false,
children : "items"
}
},
filter: { field: "module", operator: "startswith", value: "Accounting" }
});
$("#AccountingTree").kendoTreeView({
check: onCheck,
checkboxes: { checkChildren: true } ,
dataSource: dataSource,
dataBound: function(){
this.expand('.k-item');
},
dataTextField: ["module","groupname","programName","checked"]
});
Found it. Basically I just call
change: function(e){
dataSource.read()
}
whenever i cancelled the updating process from the child node,the child node just merge with root node,i don't find error in the console or i can't find anything suspicious.but after a reload,all becomes normal
$(document).ready(function () {
var windowTemplate = kendo.template($("#windowTemplate").html());
var dataSource = new kendo.data.TreeListDataSource({
transport: {
read: {
url: "officeprofiletree",
type: 'POST',
dataType: "json"
},
update: {
url: "officeprofilenametree_update",
type: 'POST',
contentType :'application/json',
dataType: "json"
},
destroy: {
url: "officeprofilenametree_destroy",
type: 'POST',
contentType :'application/json',
dataType: "json"
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models)
{
return JSON.stringify(options.models);
}
}
},
batch: true,
sort: { field: "name", dir: "asc" },
schema: {
model: {
id: "officeProfileNMId",
parentId: "parentId",
fields: {
officeProfileNMId: { type:"number" },
parentId:{nullable:true,type:"number"},
mobile:{ type:"string"},
address:{type:"string"},
phone: {type:"string"},
},
}
}
});
var window = $("#window").kendoWindow({
visible:false,
title: "Are you sure you want to delete this record?",
width: "450px",
height: "60px",
}).data("kendoWindow");
var treelist = $("#treelist").kendoTreeList({
dataSource: dataSource,
pageable: true,
dataBound: function (){
var tree = this;
var trs = this.tbody.find('tr').each(function(){
var item = tree.dataItem($(this));
if( item.parentId == null) {
$(this).find('.k-button,.k-button').hide();
}
});
},
columns: [
{ field: "name", title: "Name"},
{ field: "mobile", title:"Mobile", format: "{0:c}", hidden: true },
{ field: "address", title:"Address",hidden: true },
{ field: "phone",title:"Phone" ,hidden: true },
{ command: [
{name: "edit"},
{name: "Delete",
click: function(e){
e.preventDefault();
var tr = $(e.target).closest("tr");
var data = this.dataItem(tr);
window.content(windowTemplate(data));
window.center().open();
$("#yesButton").click(function(){
treelist.dataSource.remove(data);
treelist.dataSource.sync();
window.close();
reloading();
})
$("#noButton").click(function(){
window.close();
})
}
}
]}
] ,
editable: {
mode: "popup",
},
}).data("kendoTreeList");
});
the updation and deletion works fine by the way,Here is the fiddle
https://jsfiddle.net/me09jLy7/2/
updation:
whenever i create a child to ranikannur gives me 3 children with same name in each root ranikannur,in my database there is only one child is parented by ranikannur but treelist shows it as 3 children in each parent node,the children count 3 is getting from the total ranikannurparent nodes(here tree has 3 ranikannur parent nodes)
i guess.how is this getting the 3 children?
u just try it...
$(document).ready(function () {
var windowTemplate = kendo.template($("#windowTemplate").html());
var dataSource = new kendo.data.TreeListDataSource({
transport: {
read: {
url: "officeprofiletree",
type: 'POST',
dataType: "json"
},
update: {
url: "officeprofilenametree_update",
type: 'POST',
contentType :'application/json',
dataType: "json"
},
destroy: {
url: "officeprofilenametree_destroy",
type: 'POST',
contentType :'application/json',
dataType: "json"
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models)
{
return JSON.stringify(options.models);
}
}
},
batch: true,
sort: { field: "name", dir: "asc" },
schema: {
model: {
id: "officeProfileNMId",
parentId: "parentId",
fields: {
officeProfileNMId: { type:"number" },
parentId:{nullable:true,type:"number"},
mobile:{ type:"string"},
address:{type:"string"},
phone: {type:"string"},
},
}
}
});
var window = $("#window").kendoWindow({
visible:false,
title: "Are you sure you want to delete this record?",
width: "450px",
height: "60px",
}).data("kendoWindow");
var treelist = $("#treelist").kendoTreeList({
dataSource: dataSource,
pageable: true,
dataBound: function (){
var tree = this;
var trs = this.tbody.find('tr').each(function(){
var item = tree.dataItem($(this));
if( item.parentId == null) {
$(this).find('.k-button,.k-button').hide();
}
});
},
columns: [
{ field: "name", title: "Name"},
{ field: "mobile", title:"Mobile", format: "{0:c}", hidden: true },
{ field: "address", title:"Address",hidden: true },
{ field: "phone",title:"Phone" ,hidden: true },
{ command: [
{name: "edit"},
{name: "Delete",
click: function(e){
e.preventDefault();
var tr = $(e.target).closest("tr");
var data = this.dataItem(tr);
window.content(windowTemplate(data));
window.center().open();
$("#yesButton").click(function(){
treelist.dataSource.remove(data);
treelist.dataSource.sync();
window.close();
reloading();
})
$("#noButton").click(function(){
window.close();
})
}
}
]}
] ,
editable: {
mode: "popup",
},
}).data("kendoTreeList");
});
I have a Treeview. On selecting the edit of the treenode a kendo grid for Roles will be displayed and few textboxes (where is edit other properties for roles). The kendo grid for roles have checkboxes and Rolenames. My current code is working if I select one checkbox.
What I need is how I get the array of the ids of the roles if I check multiple checkboxes. Tried multiple ways but I am not getting the list of ids when multiple checkboxes are selected. On click edit of the node EditNode is triggered and on click of save the 'click' is trigerred.
Below is my code:
function editNode(itemid) {
var editTemplate = kendo.template($("#editTemplate").html());
var treeview = $("#treeview").data("kendoTreeView");
var selectedNode = treeview.select();
var node = treeview.dataItem(selectedNode);
$("<div/>")
.html(editTemplate({ node: node }))
.appendTo("body")
.kendoWindow({
title: "Node Details",
modal: true,
open: function () {
console.log('window opened..');
editDS = new kendo.data.DataSource({
schema: {
data: function (response) {
return JSON.parse(response.d); // ASMX services return JSON in the following format { "d": <result> }.
},
model: {// define the model of the data source. Required for validation and property types.
id: "Id",
fields: {
Id: { editable: false, nullable: false, type: "string" },
name: { editable: true, nullable: true, type: "string" },
NodeId: { editable: false, nullable: false, type: "string" },
}
},
},
transport: {
read: {
url: "/Services/MenuServices.asmx/getroles",
contentType: "application/json; charset=utf-8", // tells the web service to serialize JSON
type: "POST", //use HTTP POST request as the default GET is not allowed for ASMX
datatype: "json",
},
}
});
rolesGrid = $("#kgrid").kendoGrid({
dataSource: editDS,
height: 150,
pageable: false,
sortable: true,
binding: true,
columns: [
{
field: "name",
title: "Rolename",
headerTemplate: '<span class="tbl-hdr">Rolename</span>',
attributes: {
style: "vertical-align: top; text-align: left; font-weight:bold; font-size: 12px"
}
},
{
template: kendo.template("<input type='checkbox' class = 'checkbox' id='chkbx' data-id='#:Id #' />"),
attributes: {
style: "vertical-align: top; text-align: center;"
}
},
],
}).data('KendoGrid');
},
})
.on("click", ".k-primary", function (e) {
var dialog = $(e.currentTarget).closest("[data-role=window]").getKendoWindow();
var textbox = dialog.element.find(".k-textbox");
var LinKLabel = $('#LL').val();
var roles = $(chkbx).data('roleid');
console.log(PageLocation);
node.text = undefined;
node.set("LINK_LABEL", LinKLabel);
node.set("Roles", roles);
dialog.close();
var treenode = treeview.dataSource.get(itemid);
treenode.set("LINK_LABEL", LinKLabel);
treenode.set("id", Id);
treenode.set("roles", roles);
treenode.LINK_LABEL = LinKLabel;
treenode.ID = Id;
treenode.roles = roles;
var rid = $(chkbx).data('roleid');
$.ajax({
url: "/Services/MenuServices.asmx/UpdateTreeDetails",
contentType: "application/json; charset=utf-8",
type: "POST",
datatype: "json",
data: JSON.stringify({ "Json": treenode })
});
console.log(JSON.stringify(treenode));
})
}
I'm assuming you want to get those ids in this line:
var roles = $(chkbx).data('roleid');
Right? What I don't know is the format you want to get that data. With the following code you can get the roles data in an array objects like this { id: 1, value: true }, check it out:
var grid = $("#grid").data("kendoGrid"),
ids = [];
$(grid.tbody).find('input.checkbox').each(function() {
ids.push({
id: $(this).data("id"),
value: $(this).is(":checked")
});
});
Demo. Anyway you want it, you can change it inside the each loop.
Update:
To get only the checked checkboxes, change the selector to this:
$(grid.tbody).find('input.checkbox:checked')
Demo
I have a Kendo UI Grid that displays n-child records, that I also have a custom resize function that keeps the grid sized for the browser window height. If I remove that resizeListener, the child records display as appropriate. If I have the resizeListener bound, the child records do not display.
This issue is specific to Internet Explorer 8 (sorry, it's a company policy limitation). The grid functions normally in Firefox.
I have tried using $(window).off("resize") when I activate the child template, in the databound, and in really a variety of random places that I thought might possibly work - but nothing so far.
I'm looking for a solution or a work-around for IE.
Here is the function:
function resizeGrid() {
var gridElement = $("#boxesgrid");
var dataArea = gridElement.find(".k-grid-content");
var newGridHeight = $(document).height() > 850 ? 850 : $(document).height() * .75;
var newDataAreaHeight = newGridHeight * .7;
dataArea.height(newDataAreaHeight);
gridElement.height(newGridHeight);
gridElement.data("kendoGrid").refresh();
}
var resizeListener = function () {
$(window).one("resize", function () {
resizeGrid();
setTimeout(resizeListener, 500);
});
};
Here is the html:
<div class="col-md-2">
<div class="panel panel-default">
<div class="panel-heading">Line of Business</div>
<div class="panel-body" id="lobnav"></div>
</div>
<div class="panel panel-default">
<div class="panel-heading">Application</div>
<div class="panel-body" id="lobapp"></div>
</div>
<div class="panel panel-default">
<div class="panel-heading">Filter</div>
<div class="panel-body" id="jobfilter">
</div>
</div>
</div>
<div class="col-md-10">
<div id="boxesgrid"></div>
</div>
Here is the rest of the javascript/kendo code:
$(document).ready(function () {
resizeListener();
var isParent, appId, lobId, boxId;
var apiUrl = '#ViewBag.ApiUrl';
var lobDataSource = new kendo.data.DataSource({
transport: {
read: {
url: apiUrl + "Lob"
}
},
schema: {
model: {
id: "LobId",
hasChildren: "HasChildren"
}
}
});
var appsDataSource = new kendo.data.DataSource({
transport: {
read: {
url: apiUrl + "App"
},
parameterMap: function (data, action) {
if (action === "read") {
data.lobid = lobId;
data.parent = isParent;
return data;
} else {
return data;
}
}
}
});
var filterDataSource = new kendo.data.DataSource({
transport: {
read: {
url: apiUrl + "Theme"
}
},
schema: {
model: { id: "FilterId" }
}
});
var boxesDataSource = new kendo.data.DataSource({
transport: {
read: {
url: apiUrl + "Process"
},
parameterMap: function (data) {
data.appid = appId;
data.parent = isParent;
data.lobid = lobId;
return kendo.stringify(data);
}
},
schema: {
data: "Data",
total: "Total",
model: { id: "JobId" }
},
serverPaging: true,
serverFiltering: true,
serverSorting: true
});
var lobnav = $("#lobnav").kendoTreeView({
select: function (e) {
var tree = this;
var src = tree.dataItem(e.node);
lobId = src.LobId;
isParent = src.HasChildren;
},
change: function (e) {
appsDataSource.read();
},
dataSource: {
transport: {
read: {
url: apiUrl + "Lob"
}
},
schema: {
model: {
id: "LobId",
hasChildren: "HasChildren"
}
}
},
loadOnDemand: false,
dataTextField: "LobName"
});
var appnav = $("#lobapp").kendoListView({
selectable: "single",
autoBind: false,
change: function () {
var idx = this.select().index();
var itm = this.dataSource.view()[idx];
appId = itm.AppId;
boxesDataSource.query({
page: 1,
pageSize: 35
});
},
template: "<div class='pointercursor'>${AppName}</div>",
dataSource: appsDataSource
});
var jobsfilter = $("#jobfilter").kendoListView({
selectable: "single",
loadOnDemand: false,
template: "<div class='pointercursor' id=${FilterId}>${FilterName}</div>",
dataSource: filterDataSource,
dataBound: function () {
var dsource = $("#jobfilter").data("kendoListView").dataSource;
if (dsource.at(0).FilterName !== "All") {
dsource.insert(0, { FilterId: 0, FilterName: "All" });
}
},
change: function () {
var itm = this.select().index(), dataItem = this.dataSource.view()[itm];
var appDs = appsDataSource.view(), apps = $("#lobapp").data("kendoListView"),
selected = $.map(apps.select(), function (item) {
return appDs[$(item).index()].AppName;
});
if (selected.length > 0) {
if (dataItem.FilterId !== 0) {
var $filter = new Array();
$filter.push({ field: "JobStatusId", operator: "eq", value: dataItem.FilterId });
jgrid.dataSource.filter($filter);
} else {
jgrid.dataSource.filter({});
}
}
}
});
var jgrid = $("#boxesgrid").kendoGrid({
columns: [
{
field: "AppName",
title: "App"
},
{
field: "JobId",
title: "Job Id"
},
{
field: "JobName",
title: "Job Name",
},
{
field: "JobStatus",
title: "Status"
},
{
field: "JobStatusId",
title: "Status Code"
},
{
field: "HasChildren",
title: "Has Children"
},
{
field: "ChildrenCount",
title: "Child Jobs"
}
],
sortable: {
mode: "single",
allowUnsort: true
},
pageable: {
pageSizes: [35],
numeric: true,
refresh: true,
pageSize: 35
},
autoBind: false,
scrollable: true,
resizable: true,
detailInit: detailInit,
dataSource: boxesDataSource
}).data("kendoGrid");
function detailInit(e) {
var eventData = e;
$.ajax({
url: apiUrl + "ProcessJobs",
type: "POST",
data: {BoxId: e.data.JobId, AppId: e.data.AppId},
dataType: "json",
success: function(data, status, xhr) {
initializeDetailGrid(eventData, data);
}
});
};
function initializeDetailGrid(e, result) {
var moreChildren = result[0].HasChildren;
var gridBaseOptions = {
dataSource: result,
scrollable: false,
sortable: true,
columns: [
{
field: "ParentJobId",
title: "Parent Job"
},
{
field: "JobId",
title: "Job Id"
},
{
field: "JobName",
title: "Job Name",
},
{
field: "JobStatus",
title: "Status"
},
{
field: "JobStatusId",
title: "Status Code"
},
{
field: "HasChildren",
title: "Has Children"
},
{
field: "ChildrenCount",
title: "Child Jobs"
}
]
};
var gridOptions = {};
if (moreChildren) {
gridOptions = $.extend({}, gridBaseOptions, { detailInit: detailInit });
} else {
gridOptions = gridBaseOptions;
};
$("<div/>").appendTo(e.detailCell).kendoGrid(gridOptions);
};
});
The resize function needed to be changed. The error was calling refresh on the grid, rather than resize. The corrected function looks like:
function resizeGrid() {
var gridElement = $("#boxesgrid");
var newGridHeight = $(window).height() > 800 ? 800 : $(document).height() * .75;
gridElement.height(newGridHeight);
gridElement.data("kendoGrid").resize();
}
Setting the data area separately was incorrect, as well.
I'm working with Kendo UI's Grid and attempting to add some code which preserves the grid's filter/grouping/etc by way of a cookie. It works in the example, but not at all in my code.
Example: http://www.kendoui.com/code-library/web/grid/preserve-grid-state-in-a-cookie.aspx
My Code: http://jsfiddle.net/PwajE/
For whatever reason (I'm sure it's a simple one) I keep getting type errors. Two hours later... here I am.
As always, any help is appreciated.
#RRfive
<script>
var data = [{"name":"John Smith","email":"test#test.com","permission":"admin","costRate":"60","dt":"2013-02-02 10:26:29","memberID":"M0000001"},{"name":"Test Simple","email":"test#jones.com","permission":"user","costRate":"40","dt":"2013-02-02 00:00:00","memberID":"M0000002"}];
$(document).ready(function() {
$("#grid").kendoGrid({
dataSource: {
data: data,
//transport: {
// read: "assets/data/data.users.php",
//},
schema: {
data: function(result) {
return result.data || result;
},
total: function(result) {
var data = this.data(result);
return data ? data.length : 0;
},
model:{
id:"memberID",
fields:{
dt:{ type:"date" },
costRate:{ type:"number" }
}
}
},
pageSize: 10,
},
sortable: {
mode: "single",
allowUnsort: true,
},
pageable: {
input: true,
numeric: false
},
reorderable: true,
resizable: true,
filterable: {
extra:false,
operators: {
string:{
contains: "Contains",
}
}
},
columnMenu: false,
groupable: true,
dataBound: function(e){
var grid = this;
var dataSource = this.dataSource;
var state = kendo.stringify({
page: dataSource.page(),
pageSize: dataSource.pageSize(),
sort: dataSource.sort(),
group: dataSource.group(),
filter: dataSource.filter()
});
$.cookie("employeesState",state);
if($.cookie('empRows')){
$.each(JSON.parse($.cookie('empRows')),function(){
var item = dataSource.get(this);
var row = grid.tbody.find('[data-uid='+item.uid+']');
row.addClass('k-state-selected');
})
}
},
change:function(){
var grid = this;
var ids = grid.select().map(function(){
return grid.dataItem($(this)).Id
}).toArray();
$.cookie('empRows',JSON.stringify(ids));
},
columns: [
{ field: "name", title:"Name" },
{ field: "email", title:"Email/Username" },
{ field: "costRate", title:"Cost Rate (p/hr)", template: '#= kendo.toString(costRate, "c") #', },
{ field: "permission", title:"Permission", template: "#= (permission == 'admin') ? 'Administrator' : 'User' #" },
{ field: "dt", title:"Registered", template: '#= kendo.toString(dt,"d-M-yyyy") #' },
{ field: "memberID", title:" ", width: "83px", filterable: false, sortable: false, template: '<a class="k-button k-button-icontext k-grid-edit" href="manage_admin.php?form=editMember&ID=#= kendo.toString(memberID, "n2")#"><span class=\"k-icon k-edit\"></span>Edit</a>'},
]
});
var state = JSON.parse($.cookie("employeesState"));
if(state){
if(state.filter){
parseFilterDates(state.filter, grid.dataSource.options.schema.model.fields);
}
grid.dataSource.query(state);
}
else{
grid.dataSource.read();
}
});
function parseFilterDates(filter, fields){
if(filter.filters){
for(var i = 0; i < filter.filters.length; i++){
parseFilterDates(filter.filters[i], fields);
}
}
else{
if(fields[filter.field].type == "date"){
filter.value = kendo.parseDate(filter.value);
}
}
}
</script>
If you debug that fiddle you would see that the following line throws the error:
grid.dataSource.query(state);
The reason for this is that grid is not an instance of Kendo Grid but the div elemen with id='grid'. The fix is simple - initialize the grid variable prior to using it:
var grid = $("#grid").data('kendoGrid');
grid.dataSource.query(state);