Hello Telerik,
We are using kendo controls for over the past 5 years, and we have recently noticed a bug with the hierarchy grid's child's which contain date columns and filters. We always initialize detail grids on detailnit of master grid, by passing the data which is rendered as a list from master model.
So, to give you an example. Imagine we have a master grid defined like below :
01.
@(Html.AthenaParameterConfigGrid<StudentItineraryResult>()
02.
.Name(
"studentItinerary"
)
03.
.Columns(columns =>
04.
{
05.
columns.Bound(e => e.Person.Id).Hidden();
06.
08.
columns.Bound(e => e.Person.FathersName).Width(200);
09.
columns.Bound(e => e.Person.MothersName).Width(200);
10.
columns.Bound(e => e.Person.Email).Width(200);
11.
23
24.
})
25.
.Scrollable(s => s.Enabled(
true
).Height(
"auto"
))
26.
.Sortable()
27.
.Groupable(gr => gr.Enabled(
false
))
28.
.HtmlAttributes(
new
{ @
class
=
"hide-vertical-scrollbar atn-tabstrip-grid atn-grid-dropdown-menu"
})
29.
.ClientDetailTemplateId(
"itineraries"
)
30.
.AutoBind(
false
)
31.
.DataSource(dataSource => dataSource
32.
.Ajax()
33.
.PageSize(10)
34.
.ServerOperation(
false
)
35.
.Model(model => model.Id(p => p.StudentId))
36.
.Read(read => read.Action(
"StudentItinerariesSearch"
,
"Student"
).Data(
"athena.studentItineraries.searchRequestData"
))
37.
.Events(events => events
38.
.Error(
"athena.utilities.onErrorSearch"
).RequestEnd(
"athena.utilities.laddaStop"
)
39.
)
40.
)
41.
.Events(events => events.DetailInit(
"athena.studentItineraries.detailInit"
))
42.
.Deferred())
And a detail template grid initialized again server side with no datasource read options configured, where BusStopArrivalTime and AtttendeeEventDate(and other fields that we dont show in this case) are proper DateTime fields.<script id=
"itineraries"
type=
"text/kendo-tmpl"
>
@(Html.Kendo().TabStrip()
.Name(
"tabStrip_#=StudentId#"
)
.SelectedIndex(0)
.Animation(animation => animation.Open(open => open.Fade(FadeDirection.In)))
.Items(items =>
{
items.Add().Text(@Html.GetResource(common,
"TabStripBasic"
)).Content(@<text>
@(Html.AthenaParameterConfigGrid<StudentItineraryFlat>()
.Name(
"grid_#=StudentId#"
)
.Columns(columns =>
{
columns.Bound(o => o.BusStopLabel).Hidden();
columns.Bound(o => o.BusRouteLabel).Width(250);
columns.Bound(o => o.BusStopName).Width(100);
columns.Bound(o => o.AttendeeStatusUserString).Width(80);
// TODO : filtering here does not want to work...
columns.Bound(o => o.BusStopArrivalTime).Width(80).ClientTemplate(
"\\#= BusStopArrivalTime !=null ? kendo.toString(kendo.parseDate(BusStopArrivalTime), 't') : '' \\#"
).Filterable(filterable => filterable.UI(GridFilterUIRole.TimePicker));
// TODO : filtering here does not want to work...
columns.Bound(o => o.AttendeeEventDate).Width(80).ClientTemplate(
"\\#= AttendeeEventDate !=null ? kendo.toString(kendo.parseDate(AttendeeEventDate), 'd') : '' \\#"
).Filterable(filterable => filterable.UI(GridFilterUIRole.DatePicker));
columns.Bound(o => o.AttendeeCronLabel).Width(100);
columns.Bound(o => o.AttendeeComment).Width(150);
columns.Bound(o => o.ProfileOuSpecialtySemesterLabel).Width(200);
})
.AutoBind(
false
)
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(5)
.ServerOperation(
false
)
.Model(model =>
{
model.Id(c => c.AttendeeId);
})
)
.Events(ev => ev.DataBinding(
"athena.studentItineraries.childDataBinding"
).DataBound(
"athena.studentItineraries.childDataBound"
))
.Sortable(x => x.Enabled(
true
))
.Filterable(x => x.Enabled(
true
))
.Pageable(pgb => pgb.Enabled(
false
))
.Groupable(gr => gr.Enabled(
false
))
.ToClientTemplate())
</text>
);
}).Deferred()
.ToClientTemplate()
)
</script>
So, in the detailInit of the master grid, we take the data from sender event(master grid), and we fill child's grid dataSource.data with this list of data like below:
function
detailInit(e) {
var
grid = $(
"#grid_"
+ e.data.StudentId).data(
"kendoGrid"
);
if
(e.data.HasAttendee) {
// feed child grid with master data;
grid.dataSource.data(e.data.ItinerariesFlattened.toJSON());
}
}
So the problem here is, that our datetime fields as described above, are not working. After a bit research, i found that e.data.ItinerariesFlattened or e.data.ItinerariesFlattened.toJSON(), if i log the data to console i have an object like this
....
//other string fields
BusRouteEndDate:
"/Date(1561237200000)/"
,
BusRouteStartDate:
"/Date(1538341200000)/"
BusStopArrivalTime:
"/Date(1554784800000)/"
...
//other string fields here
So i realized that date time fields, come in a format that was serialized during the first request. I have found a work around where I parse the datetime fields and then i feed the grid, which results in proper working date time fields. As shown below:
function
detailInit(e) {
var
grid = $(
"#grid_"
+ e.data.StudentId).data(
"kendoGrid"
);
if
(e.data.HasAttendee) {
// feed child grid with master data;
var
parsedData = e.data.ItinerariesFlattened.map(
attendee => {
var
model = attendee || {};
model.AttendeeEventDate = w.kendo.parseDate(attendee.AttendeeEventDate);
model.BusStopArrivalTime = w.kendo.parseDate(attendee.BusStopArrivalTime);
return
model;
}
);
grid.dataSource.data(parsedData);
}
}
So, after this try, where I hard 'coded' parsed the model fields i want, I have a dataSource where the date fields as described above, are proper date javascript object's, and not string like '"/Date(1538341200000)/"'. After this workaround, my date fields filtering works without a problem. But as i mentioned, I think that this way is hard coded and not easy to maintain, because we have always to check client side too, e.g if a property name will change, or if we want to add more date properties to the model.
So, is there any way I have proper bind my child grid from master's grids rendered data and all type of fields(maybe there are problems with other types too like boolean or smthn else dont know) ?
Thnx in advance