Won't Fix
Last Updated: 30 Nov 2020 20:18 by Aaron
Aaron
Created on: 13 Nov 2020 21:49
Category: Grid
Type: Bug Report
1
setOptions() Fails on Grid Generated by HTML Helper Bound to Model Property Using Client Operations

It's kind of difficult to describe in the subject, but here's the scenario. In an ASP.NET Core 3.1 web app, we have some different Kendo Grids that are generated by using the HTML Helper. Some of these use server operations while others do not. Following the information in the Persist State demo, I'm working on changes to save the grid options (sorting, filtering, page number, etc.) when the user navigates away from a page, then restore them the next time it's loaded. With a grid we have using server operations, this is working well so far. For a grid we have using client operations, on the other hand, I'm getting unexpected results.

 

Example:

@(Html.Kendo().Grid(new[]
   {
      new { ProductName = "Product 1", UnitPrice = 3.50 },
      new { ProductName = "Product 2", UnitPrice = 5.30 }
   })
   .Name("TestGrid")
   .NoRecords(n => n.Template("No records found"))
   .Columns(columns =>
   {
      columns.Bound(p => p.ProductName);
      columns.Bound(p => p.UnitPrice);
   })
   .DataSource(dataSource => dataSource
       .Ajax()
       .PageSize(20)
       .ServerOperation(false)
   )
)
<script>
   $(document).ready(function () {
      var grid = $("#TestGrid").data("kendoGrid");
      var options = grid.getOptions();
      grid.setOptions(options);
   });
</script>

 

If you comment out the JavaScript, you get a working grid. With the JavaScript in place, this should get the options from the grid, then immediately re-apply those same options (just for testing purposes) and the grid should end up looking the same as it did before. However, the setOptions() call seems to be triggering a POST back to the same page (with the data "sort=&group=&filter=") then wiping the data from the grid and showing the "No records found" message. However, since this grid is bound to a model property and has ServerOperation(false), all of the data needed is already at the client and there is no Ajax request that exists to get this data.

 

This is the code from viewing the source that was rendered by the code in the View from above:

<div id="TestGrid" name="TestGrid"></div><script>kendo.syncReady(function(){jQuery("#TestGrid").kendoGrid({"noRecords":{"template":"No records found"},"columns":[{"title":"Product Name","field":"ProductName","filterable":{"messages":{"selectedItemsFormat":"{0} selected items"},"checkAll":false},"encoded":true},{"title":"Unit Price","field":"UnitPrice","filterable":{"messages":{"selectedItemsFormat":"{0} selected items"},"checkAll":false},"encoded":true}],"scrollable":false,"dataSource":{"type":(function(){if(kendo.data.transports['aspnetmvc-ajax']){return 'aspnetmvc-ajax';} else{throw new Error('The kendo.aspnetmvc.min.js script is not included.');}})(),"transport":{"read":{"url":""},"prefix":""},"pageSize":20,"page":1,"groupPaging":false,"total":2,"schema":{"data":"Data","total":"Total","errors":"Errors","model":{"fields":{"ProductName":{"editable":false,"type":"string"},"UnitPrice":{"editable":false,"type":"number"}}}},"data":{"Data":[{"ProductName":"Product 1","UnitPrice":3.5},{"ProductName":"Product 2","UnitPrice":5.3}],"Total":2}}});});</script>
<script>
   $(document).ready(function () {
      var grid = $("#TestGrid").data("kendoGrid");
      var options = grid.getOptions();
      grid.setOptions(options);
   });
</script>

 

I'm not sure why it's attempting an Ajax request, but that appears to be what's causing the problems. With the other grid we have that *does* use server operations, I'm assuming we're not having this same problem because it does actually require an Ajax request to read the data.

3 comments
Aaron
Posted on: 30 Nov 2020 20:18

Sorry, that simplified example was based partially on the Binding to local data demo (I'm not sure why the demo is specifying an Ajax data source when it's binding to the view's model). I did confirm that specifying a custom data source as you suggested does appear to resolve the issue (although it doesn't seem like this should be necessary... but if it fixes the issue, it's easy enough to include).

 

However, this introduces a new problem. When the custom data source is used along with Pageable(), the pager displays "NaN - NaN of 2 items" in the bottom-right corner. This can be reproduced by taking the code you provided and adding Pagable() to it:

@(Html.Kendo().Grid(new[]
   {
      new { ProductName = "Product 1", UnitPrice = 3.50 },
      new { ProductName = "Product 2", UnitPrice = 5.30 }
   })
   .Name("TestGrid")
   .NoRecords(n => n.Template("No records found"))
   .Columns(columns =>
   {
      columns.Bound(p => p.ProductName);
      columns.Bound(p => p.UnitPrice);
   })
   .DataSource(dataSource => dataSource
       .Custom()
   )
.Pageable() )

 

Note that this is just a simplified example for the purpose of troubleshooting and discussion. In our real scenario, we aren't simply passing the data directly into the HTML Helper like this, the grid is bound to a property of the view's model. Without specifying the DataSource() at all, the pager is fine and shows the correct numbers (but has the problem with getOptions()/setOptions()). After adding the custom DataSource(), that fixes the problem with getOptions()/setOptions() but introduces the problem with the pager.

ADMIN
Angel Petrov
Posted on: 20 Nov 2020 14:00

Hello Aaron,

The problem lies in the transport used. The sample uses Ajax where it is not needed when binding to local data. By modifying it to custom as shown below all should work as expected.

@(Html.Kendo().Grid(new[]
   {
      new { ProductName = "Product 1", UnitPrice = 3.50 },
      new { ProductName = "Product 2", UnitPrice = 5.30 }
   })
   .Name("TestGrid")
   .NoRecords(n => n.Template("No records found"))
   .Columns(columns =>
   {
      columns.Bound(p => p.ProductName);
      columns.Bound(p => p.UnitPrice);
   })
   .DataSource(dataSource => dataSource
       .Custom()
   )
)
<script>
    $(document).ready(function () {
        var grid = $("#TestGrid").data("kendoGrid");
        var options = grid.getOptions();
       
        grid.setOptions(options);
    });
</script>

Regards,
Angel Petrov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Aaron
Posted on: 13 Nov 2020 22:15
Also, for what it's worth... if I replace the HTML Helper with the resulting code that it renders, the problem still occurs (as expected). However, if I comment out some specific lines, that gets it working again. I've attached an example file since it doesn't look like I can include formatted code in a comment. While this kind of helps identify what in particular is causing the problem, it's also not all that helpful to me because I'm not sure how I would go about achieving this same result using HTML Helpers (other than maybe specifying a custom DataSource, which doesn't seem like it should at all be necessary).
Attached Files: