Unable to get property 'length' of undefined or null reference kendo.web.min.js, line 10 character 28275
Step 2. See attached JavaScript error when GroupBy.png, I get the JavaScript error.
The code I am using looks to me to be identical to the Custom AJAX Binding sample code included in the examples, but I am getting this error?
.CSHTML
@(Html.Kendo().Grid<
Fluid
>()
.Name("Grid")
.Columns(columns => {
columns.Bound(o => o.FluidID).Groupable(false);
columns.Bound(o => o.Name);
columns.Bound(o => o.Code);
columns.Bound(o => o.Grade);
columns.Bound(o => o.Manufacturer);
})
.Deferred()
.Pageable()
.Sortable()
.Filterable()
.Scrollable()
.Groupable()
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("GetJsonData", "FluidKendo"))
)
)
Controller Code:
public
ActionResult GetJsonData([DataSourceRequest] DataSourceRequest request)
{
List<Fluid> allFluids = MockFluids();
// When drag column header into group by row the following JavaScript error occurs
// JavaScript error IE: SCRIPT5007: Unable to get property 'length' of undefined or
// null reference kendo.web.min.js, line 10 character 28275
// JavaScript error Chrome: Uncaught TypeError: Cannot read property 'length' of undefined
// --- Example taken from the Custom AJAX Binding example: CustomAjaxBindingController.cs
var resultThatErrors =
new
DataSourceResult();
resultThatErrors.Data = allFluids;
resultThatErrors.Total = allFluids.Count();
return
Json(resultThatErrors);
}
Refer to the attached Highlighted VS solution items.png for the highlighted items of interest.
Thanks,
Beau
14 Answers, 1 is accepted
I have copied line for line the Custom AJAX Binding sample in which Grouping works as expected into a brand new empty MVC4 app and I still get the same error. I have even copied all the Scripts and CSS from the sample to ensure there are no script version issues etc.
It should not be this difficult, the example is very simple:
Models/Fluid.cs
public
class
Fluid
{
public
string
FluidGrade {
get
;
set
; }
public
string
Manufacturer {
get
;
set
; }
}
@(Html.Kendo().Grid<
NEW_MVC_APP.Models.Fluid
>()
.Name("Grid")
.Columns(columns => {
columns.Bound(o => o.FluidGrade);
columns.Bound(o => o.Manufacturer);
})
.Groupable()
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("CustomAjaxBinding_Read", "Home"))
)
)
public
class
HomeController : Controller
{
public
ActionResult Index()
{
return
View();
}
public
ActionResult CustomAjaxBinding_Read([DataSourceRequest] DataSourceRequest request)
{
List<Fluid> allFluids = MockFluids();
var result =
new
DataSourceResult()
{
Data = allFluids,
Total = allFluids.Count
};
return
Json(result);
}
public
List<Fluid> MockFluids()
{
List<Fluid> fluids =
new
List<Fluid>();
for
(
int
i = 1; i <= 5; i++)
{
Fluid fluid =
new
Fluid();
fluid.FluidGrade =
"Grade "
+ i.ToString();
fluid.Manufacturer =
"Manufacturer "
+ i.ToString();
fluids.Add(fluid);
}
return
fluids;
}
}
Can someone please help me and sanity check my code. It has to be something simple???
I've created another sample solution NEW MVC APP here: http://sdrv.ms/14HoHli
Thanks,
Beau
Current behavior is expected with the current configuration - please note that when the ServerOperations are enabled (by default) the PageSize configuration option of the Grid should be defined. In current scenario I would suggest to disable the ServerOperations:
@(Html.Kendo().Grid<NEW_MVC_APP.Models.Fluid>()
.Name(
"Grid"
)
.Columns(columns => {
columns.Bound(o => o.FluidGrade);
columns.Bound(o => o.Manufacturer);
})
.Groupable()
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(
false
)
.Read(read => read.Action(
"CustomAjaxBinding_Read"
,
"Home"
))
)
)
Vladimir Iliev
Telerik
That did work but the example I am using is a contrived simplified example to isolate the JavaScript error issue.
My full implementation of the Grid includes server side paging, filtering and sorting, therefore I do believe I require the ServerOperation=True.
Given your explaination above: If I set the PageSize = 10 and ServerOperation = True, I still get the JavaScript error.
What other config do I need to change to get Group by to function with ServerOperation=true
Updated simplified example:
@(Html.Kendo().Grid<
NEW_MVC_APP.Models.Fluid
>()
.Name("Grid")
.Columns(columns => {
columns.Bound(o => o.FluidGrade);
columns.Bound(o => o.Manufacturer);
})
.Groupable()
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(true)
.PageSize(10)
.Read(read => read.Action("CustomAjaxBinding_Read", "Home"))
)
)
@(Html.Kendo().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(f => f.FluidID).Title("ID").Width(50).Hidden(true);
columns.Bound(f => f.Name).Title("Name");
columns.Bound(f => f.Code).Title("Code");
columns.Bound(f => f.Grade).Title("Grade");
columns.Bound(f => f.Manufacturer).Title("Manufacturer");
columns.Bound(f => f.RowVersion).Title("RowVersion").Hidden(true).IncludeInMenu(false);
columns.Command(command => { command.Edit().Text("Edit").UpdateText("Save").CancelText("Cancel"); command.Destroy(); }).Width(182);
})
.Deferred()
.Resizable(resize => resize.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Sortable()
.ColumnMenu()
.Scrollable(s => s.Height("auto"))
.Navigatable()
.Groupable()
.Pageable(pager => pager
.Numeric(true)
.Info(true)
.PreviousNext(true)
.Refresh(true)
.PageSizes(true))
.Filterable(filterable => filterable.Extra(false))
.Events(e => e
.DataBound("fluidinline.gridOnDataBound"))
//.Change("fluidinline.grid.OnChange"))
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
.PageSize(20)
.Read(read => read.Action("EditingInline_Read", "FluidKendoInline")
.Data("fluidinline.gridOnDataSourceReadGetAdditionalData"))
.Create(create => create.Action("EditingInline_Create", "FluidKendoInline"))
.Update(update => update.Action("EditingInline_Update", "FluidKendoInline"))
.Destroy(destroy => destroy.Action("EditingInline_Destroy", "FluidKendoInline"))
.Model(model =>
{
model.Id(f => f.FluidID);
model.Field(f => f.FluidID).Editable(false);
model.Field(f => f.RowVersion).Editable(false);
})
.Events(events =>
{
events.Error("fluidinline.gridOnAjaxError");
events.RequestEnd("fluidinline.gridOnRequestEnd");
})
)
)
Beau
If you need to use ServerOperations then you should modify the Controller to return paged, sorted, filtered and grouped data based on the current request - please check the example below:
public
ActionResult CustomAjaxBinding_Read([DataSourceRequest] DataSourceRequest request)
{
List<Fluid> allFluids = MockFluids();
var result = allFluids.ToDataSourceResult(request);
return
Json(result);
}
Vladimir Iliev
Telerik
Grouping works if I use the following code thanks!
MapGridFilterPageOptions(request, searchFilter, resetPageNumber);
FluidService service =
new
FluidService();
List<Fluid> fluids = service.GetAllPaged(
ref
_GridFilterPagedOptions);
var result = fluids.ToDataSourceResult(request);
result.Total = _GridFilterPagedOptions.TotalRowsReturned;
return
Json(result);
But... I must be missing something else.
When Grouping is applied and I page to page 2 results.Data is empty after
var result = fluids.ToDataSourceResult(request);
See the attached screen shots:
page 1 grouping.png shows what the results.data looks like after grouping on the first page = All is good :-)
page 2 grouping.png shows I am returning 10 results using the ToDataSourceResult() and the result.Data has no data???
Thanks again for your patience and support Vladimir,
Beau
From the provided information we can only guess what the reason is - could you please provide runable sample where the issue is reproduced? This would help us identify the exact reason for this behavior.
Vladimir Iliev
Telerik
Thank you,
Beau
New sample application here: SampleApp Download called SampleApp.zip.
The app requires a small database. To setup the database create a DB called SAM2 and run the attached create.sql script, then modify the web.config SAM2Context connection string data source, initial catalog and userid password etc.
Please review the following files in /SAM2.Web - MVC 4 app
/SAM2.Web/Areas/Maintenance/Controllers/FluidKendoInlineController.cs and
/SAM2.Web/Areas/Maintenance/Views/FluidKendoInline/Views/Index.cshtml
I have implemented server side paging filtering and sorting and want only to return the required records for the particular page. For example if I have paged to page 3 and show 10 records per page, my database sproc only returns the 10 records for the page offset.
I have isolated the issue as follows:
What is the difference between the following ways of returning data?
METHOD 1: Extension Method
var result = data.ToDataSourceResult(request);
result.Total = TotalRowsReturnedByQuery;
return
Json(result);
var result =
new
DataSourceResult();
result.Data = data;
result.Total = TotalRowsReturnedByQuery;
return
Json(result);
Method 1: Using the ToDataSourceResult() extension does enable grouping without the JavaScript error but when paging to a new page no data is displayed. Refer to the attached images:
Method 1 - Extension Method - Page 1.png
Method 1 - Extension Method - Page 2.png
It looks like I am expected to return ALL records from page 1 to the current selected page for this to work? For example if I page to page 3 and return all results from page 1 i.e. 30 records instead of 10 records it works.
Method 2: Creating a new DataSourceResult() paging works as expected but when grouping columns I get the JavaScript error "Unable to get property 'length' of undefined or null reference"
I have included both approaches in the FluidKendoInlineController.cs, please uncomment as appropriate:
// Method 1: Extension method
// Problem: Paging doesn't work unless all data from the first page to the current page is returned?
// var result = fluids.ToDataSourceResult(request);
// result.Total = _GridFilterPagedOptions.TotalRowsReturned;
// Method 2: New DataSoureResult
// Problem: Group by columns causes JavaScript error
var result =
new
DataSourceResult();
result.Data = fluids;
result.Total = _GridFilterPagedOptions.TotalRowsReturned;
I would like server side paging to function as expected i.e. return only the required rows and be able to group columns.
Thanks once again for all your help so far, and let me know if you require anything else.
Beau
This following stackoverflow post will give you some more context:
http://stackoverflow.com/questions/14295924/todatasourceresult-extension-not-populating-datasourceresult-object
It looks like the ToDataSourceResult() method expects all the data from the first page to the current "paged" page. i.e. if I was on page 5, it would expect my database query to return records for page 1 to page 5 even though I should only have to return the page 5 records.
My alternative approach is to construct a new DataSourceResult() which allows me to return only the page of results but it errors when grouped.
How can I get "TRUE" server side paging (only return the required page of records) to work with grouping.
Thanks,
Beau
Basically the ToDataSourceResult extension method creates the paging, sorting, filtering and grouping of the data automatically for you - you should pass an IQueryable collection (the context) and the extension method will create the query to the DataBase for you. If you need to create custom Ajax binding however you should handle all operations manually - that why you receive error when you try to group the data. Please note that we already provide such example of "Custom Ajax binding" which is available witih KendoUI for ASP.NET MVC installation:
- ..\Telerik\Kendo UI for ASP.NET MVC %VERSION%\wrappers\aspnetmvc\Examples\Areas\razor\Views\web\grid\customajaxbinding.cshtml
Vladimir Iliev
Telerik
Instead of returning a List<Fluid> I should be returning an IEnumerable<AggregateFunctionsGroup> when grouped.
You mentioned "you should handle all operations manually" so I checked I was applying grouping and wasn't... Needed another set of eyes.
As you suggested I only had to include the .ApplyGrouping(request.Groups) and extension methods from the "Custom Ajax Binding" sample which I had already used as a base but not called ApplyGrouping...
Thanks for reading this novel of a post.
My code now looks like:
FluidService service =
new
FluidService();
List<Fluid> fluids = service.GetAllPaged(
ref
_GridFilterPagedOptions);
var fluidsQueryable = fluids.AsQueryable();
IEnumerable data = fluidsQueryable.ApplyOrdersGrouping(request.Groups);
var result =
new
DataSourceResult();
result.Data = data;
result.Total = _GridFilterPagedOptions.TotalRowsReturned;
return
Json(result);