Cannot read properties of undefined (reading 'field') from grid.DataSource

1 Answer 86 Views
Grid
John
Top achievements
Rank 1
John asked on 14 Feb 2024, 10:31 PM | edited on 15 Feb 2024, 01:19 PM

I've pulled ViewModel objects into my selectable grid. After a user selects rows, a submit button allows an ajax call which will post the selected objects (rows) to a controller method: 

    function submitAddressImport() {
         var grid = $("#groupAddressesImportGrid").data('kendoGrid');
         var selectedItems = grid.selectedKeyNames();
         var actualItems = [];

         if (selectedItems.length > 0) {
           selectedItems.forEach(function(key) {
            actualItems.push(grid.dataSource.get(key));
           });
         }

        kendo.ui.progress($("#groupAddressesImportGrid"), true);
        for (var i = 0; i < actualItems.length; i++) {
                $.ajax({
                type: "POST",
                url: "@Url.Action("AddAddress", "Address")",
                contentType: "application/json;",
                data: actualItems[i],  // JSON.stringify(actualItems[i]) avoids console error
                traditional: false,
                success: function (data) {
                 ...
                },
                error: function (data) {
                  ...
                },
                timeout: function (data) {
                   ...
                }, complete: function () {
                   ...
                }
            });
        }
        closeGroupAddresspopup()
    }

What is most curious about this error is that it is avoided if I use JSON.stringify() to convert the object to a JSON string. My model expects an object of a class, and if a stringified object is sent the object itself will not be null but will have all properties set to null.

When troubleshooting this, I removed the call to JSON.stringify() and encountered the console error: 

Uncaught TypeError: Cannot read properties of undefined (reading 'field')

Why does this error occur when JSON.stringify() is not used, and how can it be avoided? 

My grid is configured as follows:


            @(
                Html.Kendo().Grid(Model.groupAddresses)
                .Name("groupAddressesImportGrid")
                .HtmlAttributes(new { @class = "table-cell" })
                .Columns(columns =>
                {
                    columns.Select().Width(50);
                    columns.Bound(obj => obj.AddressType).Title("Type").Width(60);
                    columns.Bound(obj => obj.PrimaryField).Title("Primary");
                    columns.Bound(obj => obj.Address1).Title("Address");
                    columns.Bound(obj => obj.AddressCity).Title("City");
                    columns.Bound(obj => obj.State).Title("State");
                    columns.Bound(obj => obj.ZipCode).Title("Zip Code");
                    columns.Bound(obj => obj.County).Title("County");
                })
                .Sortable(_ => _.AllowUnsort(true))
                .Resizable(resizable => resizable.Columns(true))
                .Navigatable()
                .Filterable()
                .Scrollable()
                .Resizable(resize => resize.Columns(true))
                .Events(ev=>ev.Change("handleCheckBox"))
                .PersistSelection()
                .DataSource(dataSource => dataSource
                    .Ajax()
                    .Model(model => model.Id(p => p.AddressId)) 
                )
                )

1 Answer, 1 is accepted

Sort by
0
Mihaela
Telerik team
answered on 19 Feb 2024, 01:11 PM

Hello John,

Thank you for the shared code snippets.

To pass each selected data items as an object through the AJAX request, I would recommend the following appraoch:

  • Pass the stringified object to the JSON.parse() method to parse it back into a JS object.
  • Keep the "contentType" with its default value "'application/x-www-form-urlencoded; charset=UTF-8'".
    function submitAddressImport() {
         var grid = $("#groupAddressesImportGrid").data('kendoGrid');
         var selectedItems = grid.selectedKeyNames();
         var actualItems = [];

         if (selectedItems.length > 0) {
           selectedItems.forEach(function(key) {
            actualItems.push(grid.dataSource.get(key));
           });
         }
        var models = JSON.parse(JSON.stringify({ actualItems }));
        kendo.ui.progress($("#groupAddressesImportGrid"), true);
        for (var i = 0; i < models.actualItems.length; i++) {
                let item = models.actualItems[i];
                $.ajax({
                type: "POST",
                url: "@Url.Action("AddAddress", "Address")",
                data: item,
                traditional: false,
                success: function (data) {
                 ...
                },
                ...
            });
        }
        closeGroupAddresspopup()
    }

By following this approach, you can retrieve the respective Model instance in the Action method:

[HttpPost]
public JsonResult AddAddress(AddressViewModel actualItems) // i.e., the Grid binds to a collection of AddressViewModel instances
{
  ...
}

Let me know if this approach works for you.

 

Regards,
Mihaela
Progress Telerik

Stay tuned by visiting our public roadmap and feedback portal pages. If you're new to the Telerik family, be sure to check out our getting started resources, as well as the only REPL playground for creating, saving, running, and sharing server-side code.
Tags
Grid
Asked by
John
Top achievements
Rank 1
Answers by
Mihaela
Telerik team
Share this question
or