Kendo Treeview Expand Node - treeview

I have this treeview wich can have a variable number of children (some nodes can have up to 3 generations of children, some may have only one etc)
What I'm trying to do is expand a certain node when the treeview is loaded. And I have 2 problems:
1) I can't find an event/callback so that I know when the treeview is ready
2) The expand function doesn't always work ( I'll explain )
This is my treeview:
function InitializeTreeview() {
var Children_Merchants = {
transport: {
read: {
url: function (options) {
return kendo.format(websiteRootUrl + '/Merchants/Merchants/?hasParents={0}', hasParent);
}
}
},
schema: {
model: {
model: {
id: "ID",
hasChildren: true,
children: Children_Merchants
}
}
}
};
var Brandowners = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: kendo.format(websiteRootUrl + '/Merchants/GetBrandowners?databaseID={0}', selectedDatabaseID)
}
},
//change: ExpandNode, - if I call expand node like this, it works.
schema: {
model: {
id: "ID",
hasChildren: true,
children: Children_Merchants
}
}
});
$('#treeview').kendoTreeView({
dataSource: Brandowners,
animation: {
collapse: {
duration: 200,
effects: "fadeOut"
},
expand: {
duration: 200,
effects: "fadeIn"
}
},
dataTextField: "Name",
complete: function () { alert('ok'); },
//dataBound : ExpandNode,
select: OnSelect,
expand: CheckIfHasParent
}).data('kendoTreeView');
}
function ExpandNode() {
var treeview;
treeview = $("#treeview").data("kendoTreeView");
var nodeToExpand = treeview.findByText('Adam'); //dummy txt, will have from parameter
treeview.expand(nodeToExpand);
}
The databind works ok, my controllers get called, everything's fine.
So what I tried is hook up the ExpandNode function to a click of a button. The function gets called but nothing happens. BUT if I hook it up to the change event of the parents datasource, it works. Another interesting thing is that the select works so if I replace treeview.expand(...) with treeview.select(...), it works on the click.
So my questions are:
1) What event should I use for loadEnd ( or smth like that ) - so I won't have to bind the function to button click (it's still ok but I preffer on load ended) - P.S. I tried all the ones I found on the kendo forums,like: change, requestEnd, success, dataBound and they don't work. I tried sending the JSON with the property "expanded" set to TRUE, for the node in question, but that only modifies the arrow to show like it's opened, but it doesn't call the controller and load the children.
2) Do you know why ExpandNode works only when binded to the change event? - the most important question to me.
3) If you have suggestions, or have I done something wrong in the initialiation of the treeview, please tell me.

I've copied your code with some free interpretations and the answer your questions is:
What event should I use for loadEnd => dataBound
Do you know why ExpandNode works only when binded to the change event? => No, it works without binding it to change event. If it does not then there is something else in your code.
Suggestions => There is some information missing about your code that might make the difference with what I've implemented.
What is CheckIfHasParent? => I have implemented it as a function that actually does nothing.
What is hasParent? => I've ignored it.
The code as I write it:
$(document).ready(function () {
function InitializeTreeview() {
var Children_Merchants = {
transport: {
read: function (op) {
var id = op.data.ID;
var data = [];
for (var i = 0; i < 10; i++) {
var aux = id * 100 + i;
data.push({ Name: "Name-" + aux, ID: aux});
}
op.success(data);
}
},
schema : {
model: {
model: {
id : "ID",
hasChildren: true,
children : Children_Merchants
}
}
}
};
var Brandowners = new kendo.data.HierarchicalDataSource({
transport: {
read: function (op) {
op.success([
{"Name": "Adam", "ID": 1},
{"Name": "Benjamin", "ID": 2},
{"Name": "Caleb", "ID": 3},
{"Name": "Daniel", "ID": 4},
{"Name": "Ephraim", "ID": 5},
{"Name": "Frank", "ID": 6},
{"Name": "Gideon", "ID": 7}
])
}
},
//change: ExpandNode, - if I call expand node like this, it works.
schema : {
model: {
id : "ID",
hasChildren: true,
children : Children_Merchants
}
}
});
$('#treeview').kendoTreeView({
dataSource : Brandowners,
animation : {
collapse: {
duration: 200,
effects : "fadeOut"
},
expand : {
duration: 200,
effects : "fadeIn"
}
},
dataTextField: "Name",
dataBound : ExpandNode,
expand : CheckIfHasParent
}).data('kendoTreeView');
}
function ExpandNode() {
var treeview;
treeview = $("#treeview").data("kendoTreeView");
var nodeToExpand = treeview.findByText('Adam'); //dummy txt, will have from parameter
treeview.expand(nodeToExpand);
}
function CheckIfHasParent(e) {
}
InitializeTreeview();
});
and you can play with it here : http://jsfiddle.net/OnaBai/dSt2h/

$("#treeview").kendoTreeView({
animation: {
expand: true
},
dataSource: dataSource,
dataBound: function (e) {
var tv = $("#treeview").data("kendoTreeView");
if (tv != null) {
tv.expand(".k-item");
}
},
dataTextField: "test",
dataValueField: "id"
});

For anyone who may be interested:
function ExpandNode() {
var treeview;
var node1;
treeview = $("#treeview").data("kendoTreeView");
var node2;
var myURL = kendo.format(websiteRootUrl + '/Merchants/GetPathForSelectedNode?databaseID={0}&merchantID={1}&brandownerID={2}', selectedDatabaseID,MerID,BowID);
node1 = treeview.dataSource.get(BowID);
node = treeview.findByUid(node1.uid);
var uid = node1.uid;
node.find('span:first-child').trigger('click'); //expand 1st level
$.ajax( {
url: myURL,
dataType: "json",
contentType: 'application/json; charset=utf-8',
success: function(result)
{
var length = result.length;
var lastVal = 1;
for (var i = 1; i < length-1; i++) {
$("#treeview li[data-uid=\'" + uid + "\'] ul.k-group").waitUntilExists (function
() {
i = lastVal; // have to reinitialize i because waitUntilExist's callback will find the i incermented, over the needed value
lastVal++;
node2 = node1.children.get(result[i]);
node = treeview.findByUid(node2.uid);
uid = node2.uid;
node1 = node2;
if(lastVal <= length-1)
node.find('span:first-child').trigger('click'); // keep expanding
else
{
treeview.select(node); // just select last node
currentSelectedNode = node;
}
});
}
if(length == 2) //select 1st child
{
$("#treeview li[data-uid=\'" + uid + "\'] ul.k-group").waitUntilExists (function
() {
node2 = node1.children.get(result[i]);
node = treeview.findByUid(node2.uid);
uid = node2.uid;
node1 = node2;
treeview.select(node); // just select last node
currentSelectedNode = node;
});
}
}
});
}
This is my method. The for loop starts at 1 because the 1st element in my array is the 1st node ID - wich I've already expanded. the .waitUntilExists is Ryan Lester's method (I put a link in the comments above). Many thanks to my colleague, to you OnaBai and, of courese, to Ryan Lester. I hope this helps someone. Cheers

ypu can easily find the treeview is ready for expand by following code which are expanding all the treeview nodes you can also find it by checking perticular id or text
hopw, following example will help you
Ex:
$("#treeview").kendoTreeView({
animation: {
expand: true
},
dataSource: dataSource,
dataBound: function (e) {
var tv = $("#treeview").data("kendoTreeView");
if (tv != null) {
tv.expand(".k-item");
}
},
dataTextField: "test",
dataValueField: "id"
});

Related

Backbone-validation.js on Subview

I've been following an online example of backbone validation online:
http://jsfiddle.net/thedersen/c3kK2/
So far so good, but now I'm getting into validating subviews and they're not working.
My code looks like this:
var ScheduleModel = Backbone.Model.extend({
validation: {
StartDate: {
required: true,
fn: "isDate"
},
StartTime: [{
required: true
},
{
pattern: /^([0-2]\d):([0-5]\d)$/,
msg: "Please provide a valid time in 24 hour format. ex: 23:45, 02:45"
}],
EndDate: {
required: true,
fn: "isDate"
}
},
isDate: function (value, attr, computed) {
if (isNaN(Date.parse(value))) {
return "Is not a valid Date";
}
}
});
var ScheduleView = Backbone.View.extend({
tagName: "div",
template: _.template($("#scheduleAddTemplate").html()),
render: function () {
// append the template to the element
this.$el.append(this.template(this.model.toJSON()));
// set the schedule type
var renderedInterval = SetScheduleType(this.model.attributes.ScheduleType.toLowerCase());
// append to the interval
$("#Interval", this.$el).append(renderedInterval.el);
this.stickit();
return this;
},
events: {
"submit #NewScheduleForm": function (e) {
e.preventDefault();
if (this.model.isValid(true)) {
this.model.save(null,
{
success: function (schedule) {
//do stuff
}
},
{ wait: true });
}
}
},
bindings: {
"[name=ScheduleType]": {
observe: "ScheduleType",
setOptions: {
validate: true
}
},
"[name=StartDate]": {
observe: "StartDate",
setOptions: {
validate: true
}
},
"[name=StartTime]": {
observe: "StartTime",
setOptions: {
validate: true
}
},
"[name=EndDate]": {
observe: "EndDate",
setOptions: {
validate: true
}
}
},
initialize: function () {
Backbone.Validation.bind(this);
},
remove: function () {
Backbone.Validation.unbind(this);
}
});
The possible interval I'm currently working with is the following:
var MonthModel = Backbone.Model.extend({
defaults: {
DayOfMonth: 1,
MonthsToSkip: 1
},
MonthsToSkip: {
required: true,
min: 1,
msg: "Number must be greater than 1"
},
DayOfMonth: {
required: function (val, attr, computed) {
console.log(computed.ScheduleType);
if (computed.ScheduleType === "monthly") {
return true;
}
return false;
}
}
});
var MonthlyView = Backbone.View.extend({
tagName: "div",
attributes: function () {
return { id: "Monthly", class: "inline co-xs-4" };
},
template: _.template($("#monthEditTemplate").html()),
render: function () {
// append the template to the element
this.$el.append(this.template(this.model.toJSON()));
this.stickit();
return this;
},
bindings: {
"[name=DayOfMonth]": {
observe: "DayOfMonth",
setOptions: {
validate: true
}
},
"[name=MonthsToSkip]": {
observe: "MonthsToSkip",
setOptions: {
validate: true
}
}
},
initialize: function () {
Backbone.Validation.bind(this);
},
remove: function () {
Backbone.Validation.unbind(this);
}
});
Does anyone have any idea why the subview isn't validating?
Found the way to do it. Posting how it's done in case anyone else ever finds this a problem. I'm only going to show the relevant bits of code without all the bindings, initializing ect.
var ScheduleView = Backbone.View.extend({
render: function () {
// this.Interval
this.Interval = SetScheduleType(this.model.attributes.ScheduleType.toLowerCase(), this.model);
// set the changed interval view
$("#Interval", this.$el).append(this.Interval.render().el);
this.stickit();
return this;
},
events: {
"change #NewScheduleForm": function (e) {
// validate the subview when changes are made
this.Interval.model.validate();
},
"change #ScheduleType": function (e) {
e.preventDefault();
var model = this.model;
var newSchedType = e.target.value;
this.model.attributes.ScheduleType = e.target.value;
this.Interval = SetScheduleType(newSchedType, model);
$("#Interval").html(this.Interval.render().el);
},
"submit #NewScheduleForm": function (e) {
e.preventDefault();
if ((this.model.isValid(true)) && (this.Interval.model.isValid(true))) {
console.log("Success");
this.model.save(null,
{
success: function (schedule) {
//do stuff
}
},
{ wait: true });
}
}
}
});
Essentially I turned the subview into an attribute on the master view. I manually call the validation for the subview on any changes to the master view and on submitting the form.

KendoGrid - After applying custom filter and then navigating to next or any other page, the filter values are not getting passed to controller

Used Kendo Version: 2015.2.624
I have implemented kendogrid server side paging with additional parameters. Below is how my controller looks like:
public ActionResult GetData([DataSourceRequest] DataSourceRequest request, DateTime startDate, DateTime endDate, int state = -1, string poolName = null, string submitter = null)
{
poolName = string.IsNullOrEmpty(poolName) ? null : poolName;
submitter = string.IsNullOrEmpty(submitter) ? null : submitter;
var summarylist = new List<Summary>();
var total = 0;
using (var db = new SummaryEntities())
{
var jobs = db.SummaryTable.Where(k => k.created >= startDate && k.created <= endDate)
.Where(k => state != -1 ? k.state == state : k.state > state)
.Where(k => poolName != null ? k.pool_name == poolName : k.pool_name != null)
.Where(k => submitter != null ? k.submitter == submitter : k.submitter != null);
jobs = jobs.OrderByDescending(job => job.id);
total = jobs.Count();
// Apply paging...
if (request.Page > 0)
{
jobs = jobs.Skip((request.Page - 1) * request.PageSize);
}
jobs = jobs.Take(request.PageSize);
foreach (var job in jobs)
{
summarylist.Add(new Summary(job));
}
}
var result = new DataSourceResult()
{
Data = summarylist,
Total = total
};
return Json(result, JsonRequestBehavior.AllowGet);
}
additional parameters are the current values which the user has set over the widget datepicker, input box etc.
Below is how my datasource looks like in grid:
<script type="text/javascript">
j$ = jQuery.noConflict();
j$(document).ready(function () {
j$("#grid").kendoGrid({
dataSource: {
transport: {
read: {
url: "/Home/GetData/",
dataType: "json",
data: {
startDate: j$("#startdate").val(),
endDate: j$("#enddate").val()
}
}
},
pageSize: 30,
serverPaging: true,
schema: {
data: 'Data',
total: 'Total'
}
},
height: j$(window).height() - 85,
groupable: true,
sortable: true,
filterable: false,
columnMenu: true,
pageable: true,
columns: [
{ field: "JobId", title: "Job Id", template: '#:JobId#', type: "number" },
{ field: "Name", title: "Job Name", hidden: true },
{ field: "PoolName", title: "Pool Name" },
{ title: "Date Time", columns: [{ field: "Start", title: "Start" },
{ field: "End", title: "End" }
],
headerAttributes: {
"class": "table-header-cell",
style: "text-align: center"
}
},
{ field: "State", title: "State" },
{
title: "Result", columns: [{ field: "ResultPassed", title: "P" },
{ field: "ResultFailed", title: "F" }
],
headerAttributes: {
"class": "table-header-cell",
style: "text-align: center"
}
},
{ field: "Submitter", title: "Submitter" }
]
});
});
</script>
It works pretty good until I observed this issue:
Change the filter values i.e submitter, date range etc and
controller gets all this information in additional parameters where
I am taking action accordingly and it works just fine.
Now suppose the result returned from step 1 has multiple pages and
when you click next page, or last page or any other page number, the
controller gets invoked which is expected but the additional
parameters being set in step 1 is not getting passed again instead
the default values are there which is ruining everything.
Correction:
Additional parameters are getting lost at client side only.
Now please tell me what am I missing here?
Expected Result: In step 2 additional parameters should not get lost and it should be same as step 1.
Any help is appreciated.
EDITED:
Complete controller and grid code.
Thanks,
Vineet
I got the solution from telerik support team:
Reply:
The described undesired behavior can be caused by the fact that the additional parameters:
data: {
startDate: j$("#startdate").val(),
endDate: j$("#enddate").val()
}
... are set to objects, instead of a functions. If they are set as functions, the values of the corresponding inputs will be evaluated every time read() is called, and the current values will be passed (like shown in the second example in the API reference):
http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-transport.read.data

Show/Hide Columns in Boot grid when onclick - Externally

i couldn't hide a show/hide a boot grid column after onclick boot grid re-load.
The issue is it works when the page is loaded first time, but i couldn't make it work after click event. Any help is appreciated.
<th id="th_state" data-identifier="true" data-column-id="state" data-visible="false">State</th>
$('#filter_group').change(function () {
$("#employee_grid").bootgrid("reload")
$("#th_state").attr("data-visible", "true") ; // Not working....
});
$("#employee_grid").bootgrid({
ajax: true,
rowCount: [50, 100, 200, 300, 500],
columnSelection: true,
requestHandler: function (request) {
request.type = 'grid';
var citiesGroup = [];
$("#cities_group").find("option:selected").each(function (index, value) {
if ($(this).is(':selected')) {
citiesGroup.push({
state: $(this).parent().attr("label"),
city: $(this).val()
});
}
});
if (request.sort) {
request.sortBy = Object.keys(request.sort)[0];
request.sortOrder = request.sort[request.sortBy];
request.chartType = $("#chartType").val();
request.date_from = $("#date_from").val();
request.date_to = $("#date_to").val();
request.citiesGroup = citiesGroup ;
delete request.sort
}
return request;
},
responseHandler: function (response) {
$("#txt_total_connects").html(response);
return response;
},
post: function ()
{
/* To accumulate custom parameter with the request object */
return {
id: "b0df282a-0d67-40e5-8558-c9e93b7befed"
};
},
url: "response.php",
formatters: {
},
labels: {
noResults: "<b>No data found</b>",
all: "",
loading: '<b>Loading Please wait....</b>'
},
templates: {
search: "",
//header: "",
}
});

Handsontable: Updating a cell renderer at runtime

I'm using handsontable, and I want to change the background color of a cell if its value is edited and changed. I can do this easily if my data source is an array of arrays (see fiddle: http://jsfiddle.net/chiman24/3o2c3c7m/).
document.addEventListener("DOMContentLoaded", function() {
// Row Styles
var blank = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.backgroundColor = '#ABAAAA'
};
var align = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.verticalAlign = 'middle';
td.style.fontWeight = 'bold';
};
var highlight1 = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.backgroundColor = '#BDD7EE';
td.style.textAlign = 'right';
};
var changedBackgroundColor = '#cbd9e4';
var defaultBackgroundColor = 'white';
var hasChanged = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.backgroundColor = changedBackgroundColor;
};
var noChange = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.backgroundColor = defaultBackgroundColor;
};
var data = [
["1", "Hear us from heaven", "New Life Worship",
"Anderson, Jared", "something"
],
["2", "Spirit Break Out", "Kim Walker", "Walker, Kim",
"Still Believe"
]
],
dataCopy = [
["1", "Hear us from heaven", "New Life Worship",
"Anderson, Jared", "something"
],
["2", "Spirit Break Out", "Kim Walker", "Walker, Kim",
"Still Believe"
]
],
container = document.getElementById('example1'),
hot1;
//Table Row and Col Options
hot1 = new Handsontable(container, {
data: data,
fixedColumnsLeft: 1,
columnSorting: true,
colHeaders: ["id", "title", "artist", "author", "album"],
columns: [{
type: "text"
}, {
type: "text"
}, {
type: "text"
}, {
type: "text"
}, {
type: "text"
}]
});
hot1.addHook('afterChange', afterChange);
function afterChange(changes, source) {
if (source == 'edit' || source == 'autofill') {
$.each(changes, function(index, element) {
var change = element;
var rowIndex = change[0];
var columnIndex = change[1];
var oldValue = change[2];
var newValue = change[3];
var cellChange = {
'rowIndex': rowIndex,
'columnIndex': columnIndex
};
if (oldValue != newValue) {
var cellProperties = hot1.getCellMeta(
rowIndex, columnIndex);
if (newValue != dataCopy[rowIndex][
columnIndex
]) {
cellProperties.renderer = hasChanged;
} else { //data changed back to original value.
cellProperties.renderer = noChange;
}
hot1.render();
}
});
}
}
});
// noSideScroll class added to fix some containers while side scrolling the table
$(window).scroll(function() {
$('.noSideScroll').css({
'left': $(this).scrollLeft()
});
});
However, when using an array of objects, I can't get it to work. (see fiddle: http://jsfiddle.net/chiman24/24mpavga/).
var data = [{
"id": 1,
"title": "First Loved Me",
"artist": "Israel and New Breed",
"author": "Houghton, Israel",
"album": "Covered: Alive In Asia"
}, {
"id": 2,
"title": "One Thing Remains",
"artist": "Israel and New Breed",
"author": "Houghton, Israel",
"album": "Covered: Alive In Asia"
}],
dataCopy = [{
"id": 1,
"title": "First Loved Me",
"artist": "Israel and New Breed",
"author": "Houghton, Israel",
"album": "Covered: Alive In Asia"
}, {
"id": 2,
"title": "One Thing Remains",
"artist": "Israel and New Breed",
"author": "Houghton, Israel",
"album": "Covered: Alive In Asia"
}],
container = document.getElementById('example1'),
hot1;
//Table Row and Col Options
hot1 = new Handsontable(container, {
data: data,
fixedColumnsLeft: 1,
columnSorting: true,
colHeaders: ["id", "title", "artist", "author", "album"],
columns: [{
data: "id"
}, {
data: "title"
}, {
data: "artist"
}, {
data: "author"
}, {
data: "album"
}]
});
hot1.addHook('afterChange', afterChange);
function afterChange(changes, source) {
if (source == 'edit' || source == 'autofill') {
$.each(changes, function(index, element) {
var change = element;
var rowIndex = change[0];
var columnIndex = change[1];
var oldValue = change[2];
var newValue = change[3];
var cellChange = {
'rowIndex': rowIndex,
'columnIndex': columnIndex
};
if (oldValue != newValue) {
var cellProperties = hot1.getCellMeta(
rowIndex, columnIndex);
if (newValue != dataCopy[rowIndex][
columnIndex
]) {
cellProperties.renderer = hasChanged;
} else { //data changed back to original value.
cellProperties.renderer = noChange;
}
hot1.render();
}
});
}
}
Is there a way to accomplish this? I want to get it working using an array of objects because my data coming from the server will be in JSON format. I've scoured the handsontable documentation for a couple of days to no avail. Any help will be much appreciated. Thanks.
I got some help from the handsontable github forum.
Apparently, if the data source is an array of objects, then when calling "getCellMeta", instead of passing in a numerical column index, you have to pass in the column index as a property like this:
hot.getCellMeta(2, hot.propToCol(columnIndex));
Here's the updated demo
Other way to change background color of cell is use the Cell Option
...
if (oldValue != newValue){
aCell.push(
{ row: rowIndex,
col: hot.propToCol(columnIndex),
className: "cssWithBackgroundColor" });
hot.updateSettings({ cell: aCell });
}
If the user undo change you can
if ( source == 'UndoRedo.undo'){
aCell.pop();
hot.updateSettings({ cell: aCell });
}

How to access column name dynamically in Kendo Grid template

I need to access the column name dynamically in Kendo Grid template.
Code:
$("#grid").kendoGrid({
dataSource: [
{ Quantity: 2 , Amount: 650},
{ Quantity: 0, Amount: 0 },
{ Quantity: 1, Amount: 500 },
{ Quantity: 4, Amount: 1047 }
],
sortable: true,
columns: [
{
field: "Quantity",
template: function (dataItem) {
if (dataItem.Quantity == '0') {
return "--";
} else {
return dataItem.Quantity;
}
}
},
{
field: "Amount",
template: function (dataItem) {
if (dataItem.Amount == '0') {
return "--";
} else {
return dataItem.Amount;
}
}
}
]
});
Here inside the "columns -> template", I need to access the column thru variable instead of hardcoding it. How can I do that? Because in real life I will be having dynamic columns populated into dataSource and I will construct the columns array inside the for loop. Please help.
Please access this JSBIN: http://jsbin.com/egoneWe/1/edit
From what I understand, you build the columns array using something like:
var Definition = [
{ field: "Quantity" },
{ field: "Amount" }
];
var columns = [];
$.each(Definition, function (idx, item) {
columns.push({
field : item.field,
template: function (dataItem) {
...;
}
})
});
$("#grid").kendoGrid({
dataSource: data,
sortable : true,
columns : columns
});
Right? And the problem is that you want to use the same template function for several (all) columns instead of having to rewrite many.
If so, what you can do is:
var Definition = [
{ field: "Quantity" },
{ field: "Amount" }
];
var columns = [];
$.each(Definition, function (idx, item) {
columns.push({
field : item.field,
template: function (dataItem) {
return commonTemplateFunction(dataItem, item.field);
}
})
});
What I use in the columns array (columns definition for the Grid) is a function that receives two arguments: the dataItem for the row and the field's name being edited.
Then, I define the template function as:
function commonTemplateFunction(dataItem, field) {
if (dataItem[field] == '0') {
return "--";
} else {
return dataItem[field];
}
}
And your modified code is here : http://jsbin.com/egoneWe/3/edit
So, despite I cannot guess the column name, I can do the trick using the columns initiator.

Resources