This is a migrated thread and some comments may be shown as answers.

JavaScript errors when Grouping using similar example to the Custom AJAX Binding sample

14 Answers 454 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Beau
Top achievements
Rank 1
Beau asked on 27 Jun 2013, 05:25 AM
I'm getting a JavaScript error after I apply grouping.
Unable to get property 'length' of undefined or null reference kendo.web.min.js, line 10 character 28275
Step 1. See attached Drag to GroupBy row.png - Load the page and group any column
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);
}
If anyone is interested I have a Visual Studio 2012 Sample App to show the error download here: https://skydrive.live.com/redir?resid=3113F9DB92CC84B2!1997&authkey=!Nefhm5WSin4%24

Refer to the attached Highlighted VS solution items.png for the highlighted items of interest.

Thanks,
Beau


14 Answers, 1 is accepted

Sort by
0
Beau
Top achievements
Rank 1
answered on 01 Jul 2013, 12:54 AM
I still can't solve this JavaScript error when grouping.

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; }
}
Views/Home/Index.cshtml
@(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"))
    )
)
Controllers/HomeController.cs
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
0
Vladimir Iliev
Telerik team
answered on 01 Jul 2013, 06:49 AM
Hi 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"))
    )
)

Kind Regards,
Vladimir Iliev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Beau
Top achievements
Rank 1
answered on 02 Jul 2013, 05:15 AM
See below - Connection timeout issue when posting... Sorry
0
Beau
Top achievements
Rank 1
answered on 02 Jul 2013, 05:40 AM
See below - Connection timeout issue when posting... Sorry
0
Beau
Top achievements
Rank 1
answered on 02 Jul 2013, 05:42 AM
Thanks Vladimir,

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"))
    )
)
My "full" (real world) implementation that includes server side paging and sorting
@(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");
   
            })
        )
)
Thanks again,
Beau
0
Vladimir Iliev
Telerik team
answered on 03 Jul 2013, 03:08 PM
Hi 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);
}
Kind Regards,
Vladimir Iliev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Beau
Top achievements
Rank 1
answered on 03 Jul 2013, 11:41 PM
I think we are almost there.

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
0
Beau
Top achievements
Rank 1
answered on 04 Jul 2013, 08:42 PM
So my question is, when using var result = fluids.ToDataSourceResult(request); why is results.Data empty (see screen shots above) after I page and have a grouping?

0
Vladimir Iliev
Telerik team
answered on 05 Jul 2013, 11:34 AM
Hi 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.


Kind Regards,
Vladimir Iliev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Beau
Top achievements
Rank 1
answered on 05 Jul 2013, 11:38 AM
Will do. I'll send something through over the weekend.

Thank you,
Beau
0
Beau
Top achievements
Rank 1
answered on 08 Jul 2013, 12:37 AM
Hi Vladimir,

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);
METHOD 2: New DataSourceResult()
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
0
Beau
Top achievements
Rank 1
answered on 09 Jul 2013, 10:25 PM
Hi Vladimir,

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
0
Vladimir Iliev
Telerik team
answered on 10 Jul 2013, 07:06 AM
Hi 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

Kind Regards,
Vladimir Iliev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Accepted
Beau
Top achievements
Rank 1
answered on 11 Jul 2013, 01:11 AM
Fixed. 

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);
Tags
Grid
Asked by
Beau
Top achievements
Rank 1
Answers by
Beau
Top achievements
Rank 1
Vladimir Iliev
Telerik team
Share this question
or