Reputation: 2185
Hopefully, someone has a solution. We have a couple of grids that have custom multi selects on the grid columns. The issue is that JSON seems to be refusing to properly serialize/deserialize them when there's more than one option selected. this works:
a = $("#grid").data("kendoGrid").getOptions();
$("#grid").data("kendoGrid").setOptions(a);
however this breaks:
a = JSON.parse(JSON.stringify($("#grid").data("kendoGrid").getOptions()));
$("#grid").data("kendoGrid").setOptions(a);
and the annoying part of this is its definitely the serialize part of the equation that's messing up, so it's proving difficult to discover exactly how it was supposed to look vs how it actually looks after being modified. String comparison is equal. Any suggestions?
example broke: Column a has a checkbox dropdown grid filter with three options: 1, 2, 3. Choosing more than one of them breaks the grid when saved then loaded. Choosing only one or zero works.
edit: here's the grid initialization: Note that DCGrid is an override of kendo grid that sets properties common to all grids such as page size.
@(Html.DCGrid<Order>("grid")
.DataSource(dataSource => dataSource
.Ajax()
.Sort(s => { if (Request.QueryString.Keys.Count == 0) { s.Add(x => x.OrderNum).Ascending(); } })
.Model(model => model.Id(o => o.ID))
.PageSize(Settings.DefaultPageSize)
.Read(read => read.Action("Read", "OrderSearch").Data("getParameters"))
)
.Events(e => e.ColumnReorder("onColumnReorder"))
.Reorderable(r => r.Columns(true))
.ColumnMenu()
.Columns(columns =>
{
if (User.IsInRole("viewOrders"))
{
columns.Template(@<text></text>)
.ClientTemplate("#= rowCommandsUndelete(data, true, false) #")
.HtmlAttributes(new { reorderable = "false" })
.Title(" ")
.Width(86);
}
columns.Bound(o => o.OrderNum)
.Width(120);
columns.Bound(o => o.Status.Name)
.ClientTemplate("#= clientTemplateOrderStatus(data) #")
.Width(120);
columns.Bound(o => o.Priority.ID).Title("Priority").Width(100)
.Filterable(f => f.Multi(true).DataSource(ds => ds.Read(r => r.Action("GetData/Priority", "Support", new { nameField = "PriorityNum" }))).ItemTemplate("kendoGridFilterData.IDTemplate"));
columns.Bound(o => o.OrderDate)
.Width(120);
columns.Bound(o => o.DueDate)
.ClientTemplate("#= clientTemplateDueDate(data) #")
.Width(140);
columns.Bound(o => o.Product.ID)
.ClientTemplate("#=ellipseDiv(data.Product.ShortName)#")
.Title("Product")
.Filterable(f => f.Multi(true).DataSource(ds => ds.Read(r => r.Action("GetData/Product", "Support", new { idField = "ID", nameField = "ShortName" }))).ItemTemplate("kendoGridFilterData.IDTemplate"))
.Width(200);
columns.Bound(o => o.DispatchConfirmNum)
.Width(140);
.ClientTemplate(CustomGridHelperExtensions.EditTemplate("Origin", "Name") + " #if(drillToValue(data, 'Origin.H2S')) {# <span class='label label-danger margin-left-right-5px'>H2S</span> #}#")
.Width(250);
columns.Bound(o => o.OriginTank.TankNum)
.ClientTemplate("<a href='/OriginTanks?OriginId=#=data.OriginID#'>#=ellipseDiv(data.OriginTank.TankNum)#</a>")
.Width(100);
columns.Bound(o => o.OriginBOLNum)
.Width(130);
columns.Bound(o => o.Destination.Name)
.ClientTemplate("<a href='/Destinations?id= #=data.DestinationID# '>#=ellipseDiv(data.Destination.Name)#</a>")
.Title("Destination")
.Width(250);
columns.Bound(o => o.Carrier.Name)
.Title("Carrier")
.ClientTemplate("<a href='/carriers?id= #=data.CarrierID# '>#=ellipseDiv(data.Carrier.Name)#</a>")
.Width(170);
columns.Bound(o => o.Driver.FullName)
.ClientTemplate("<a href='/Drivers?IDNumber=#=data.Driver.IDNumber# '>#=ellipseDiv(data.Driver.FullName)#</a>")
.Width(170);
})
)
and this is idtemplate (javascript):
IDTemplate: function (e) {
return "<li><label class='k-label'><input type='checkbox' value='#:data.ID#'/>#:data.Name || data.all#</label></li>";
}
The only options we care about are sort, filter, column visibility, column width, and column location (for rearranging).
Upvotes: 0
Views: 446
Reputation: 2494
You can't stringify function. For example:
let test = {
label: 'this is label',
calculate: function(){
return 2 + 2;
}
};
let toString = JSON.stringify(test);
console.log(toString); //returns {"label":"this is label"}
- undefined, Functions, and Symbols are not valid JSON values. If any
such values are encountered during conversion they are either omitted (when found in an object) or changed to null (when found in an
array). JSON.stringify() can return undefined when passing in "pure"
values like JSON.stringify(function(){}) or
JSON.stringify(undefined).
Resource: JSON.stringify()
You can iterate over columns in loaded options and set properties again, something like this:
let optionsObject = JSON.parse(options);
for (let i = 0; i < optionsObject.columns.length; i++) {
let column = optionsObject.columns[i];
if (column.field) {
switch (column.field) {
case 'field1':
column.template = kendo.template($('#field-1-template').html());
break;
case 'field2':
column.template = kendo.template($('#field-2-template').html());
break;
default:
break;
}
}
}
after you set propertis for columns then set grids options:
$("#grid").data("kendoGrid").setOptions(optionsObject);
Upvotes: 1