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

[Solved] Server side paging, searching, sorting works, but everything breaks when you add grouping

5 Answers 168 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Danny
Top achievements
Rank 1
Danny asked on 05 Jan 2015, 04:59 PM
Hello,

For a project I am working on I have a kendo grid that does server side paging. We have been able to get it to work with searching and sorting, but when we try to add in .Groupable() and drag a field to be grouped by, we just get a spinning circle with the javascript error message: 

Cannot read property 'length' of undefined

We return the type DataSourceResult from the controller, which I have noticed does not have any fields for grouping information. Should we be returning a different data type? Or perhaps we need a different approach all together?

Here is my grid:

@(Html.Kendo().Grid<UserViewModel>()
          .Name("grid")
          .DataSource(dataSource => dataSource
              .Ajax()
              .Read(read => read.Action("Read", "Users").Data("getSearchData"))
              .PageSize(20)
          )
          .Columns(columns =>
          {
              columns.Bound(o => o.UserName);
              columns.Bound(o => o.Name);
              columns.Bound(o => o.Email);
              columns.Bound(o => o.Status);
              columns.Bound(o => o.OrganizationRoles).Title("Roles");
              columns.Bound(o => o.Href)
                  .ClientTemplate("<a href=\"/Users/Edit?href=${Href}&previousPage=/Users\" data-icon=\"e\" class=\"btn btn-icon\"></a>" +
                                  "<a href=\"/Users/Delete?href=${Href}&previousPage=/Users\" data-icon=\"x\" data-Id=\"1\" class=\"btn btn-icon delete-role\"></a>")
                  .Title("Actions").Sortable(false);
          })
          .Pageable()
          .Groupable()
          .Sortable(sortable => sortable
              .Enabled(true)
              .AllowUnsort(false)
              .SortMode(GridSortMode.SingleColumn))
          .Deferred()
          )

<script>
    require(['/Content/js/config.js'], function () {
        require(['jquery', 'lib/kendo/kendo.grid.min', 'lib/kendo/kendo.aspnetmvc.min'], function ($, kendogrid, kendomvc) {
            @Html.Kendo().DeferredScriptsFor("grid", false)

            $(".k-link").bind("click", function(e) {
                $('#grid').data('kendoGrid').dataSource.page(1);
            });

            $('#SearchString').keyup(function(event) {
                if (event.keyCode == 13) {
                    $('#SearchButton').click();
                }
            });

            $("#SearchButton").click(
                function () {
                    $('#grid').data('kendoGrid').dataSource.fetch();
                    $('#grid').data('kendoGrid').dataSource.page(1);
                });

            function getSearchData() {
                // Reserved property names
                // used by DataSourceRequest: sort, page, pageSize, group, filter
                return {
                    SearchString: $("#SearchString").val(),
                    SearchTypeSelected: $("#SearchTypeSelected").val(),
                    //...
                };
            };
        });
    });

</script>


And here is the controller code:

public ActionResult Read([DataSourceRequest] DataSourceRequest request, TSearchViewModel queryModelInput)
        {
            var pagingLinks = (List<Link>)TempData["Links"];
            if (pagingLinks != null && pagingLinks.FirstOrDefault() != null && !pagingLinks.FirstOrDefault().Href.StartsWith(ListHref))
            {
                TempData["PriorGridState"] = null;
                TempData["Links"] = null;
            }
            var priorGridState = TempData["PriorGridState"] as GridState;
            var gridState = new GridState(request, queryModelInput, TempData["Links"] as List<Link>, ListHref);

            // figure out what api call needed based on how the grid has changed
            var gridComparisonResult = gridState.CompareTo(priorGridState);
            if (gridComparisonResult.GoToPageOne)
            {
                request.Page = 1;
            }
            var href = gridComparisonResult.NextHref;

            var result = GetDataResult(href, request); // may need to use extension method .ToDataSourceResult()?

            TempData["PriorGridState"] = gridState;
            return Json(result, JsonRequestBehavior.AllowGet);
        }

        public virtual DataSourceResult GetDataResult(string href, DataSourceRequest request)
        {
            if (String.IsNullOrEmpty(href))
            {
                href = ListHref;
            }

            var representation = HalClient.Get<PagedHalListViewModel<TInfoViewModel, Links>>(href);

            TempData["Links"] = representation.Links.ToList();

            var result = new DataSourceResult();
            
            try
            {
                result.Data = representation.ResourceList;
                result.Total = representation.TotalResults;
                result.Data.ToDataSourceResult(request);
            } catch (Exception)
            {
                result.Total = 0;
            }

            return result;
        }

Any recommendations of how I should proceed here? I am happy to provide any additional information you might require to answer the question. And remember, everything works except for the grouping.

Thanks,
Danny







5 Answers, 1 is accepted

Sort by
0
Alexander Popov
Telerik team
answered on 07 Jan 2015, 02:58 PM
Hi Danny,

I would suggest returning the object created by the ToDataSourceResult method, instead of building your own. This should guarantee that proper data is returned and would also calculate the Total amount.

Regards,
Alexander Popov
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Danny
Top achievements
Rank 1
answered on 07 Jan 2015, 03:14 PM
Hey Alexander,

Thank you for the response. I'm not sure what you're suggesting.. We are using the ToDataSourceResult method already to build the DataSourceResult object at the end of the GetDataResult function: 

var result = new DataSourceResult();
            
            try
            {
                result.Data = representation.ResourceList;
                result.Total = representation.TotalResults;
                result.Data.ToDataSourceResult(request);   <-----------
            } catch (Exception)
            {
                result.Total = 0;
            }

Is there another usage of this method that I am missing?
0
Alexander Popov
Telerik team
answered on 07 Jan 2015, 03:48 PM
Hi Danny,

My suggestion was to omit the part where each property is manually populated. For example: 
return someDataCollection.ToDataSourceResult(request);


Regards,
Alexander Popov
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Danny
Top achievements
Rank 1
answered on 07 Jan 2015, 04:13 PM
The problem is if I do that, it will only return the first page and I am unable to navigate to other pages on the grid.
0
Alexander Popov
Telerik team
answered on 09 Jan 2015, 09:51 AM
Hello Danny,

That should not happen unless the DataSourceRequest object was not manually modified. The ToDataSourceResult will show only the data that was requested from the client-side.

Regards,
Alexander Popov
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
Tags
Grid
Asked by
Danny
Top achievements
Rank 1
Answers by
Alexander Popov
Telerik team
Danny
Top achievements
Rank 1
Share this question
or