Creating a child grid editable

7 posts, 0 answers
  1. Denlys
    Denlys avatar
    6 posts
    Member since:
    May 2016

    Posted 19 May Link to this post

    Hi support,

    I need to create a Parent/Child grid and both grids must be editable. I've seen some examples in the forum and non of them fit my scenario.

    In my case both grids uses local data binding so there's no need for .Create() .Read() .Update() .Destroy() methods in the datasource. One action return the view with the data needed to show in both grids.

    The problem I'm facing is that when I add .Editable(ed => ed.Mode(GridEditMode.InCell)) to the child grid without specifying a datasource I get this error:

        An exception of type 'System.NotSupportedException' occurred in Kendo.Mvc.dll but was not handled in user code
        Additional information: There is no DataSource Model Id property specified.

    Now if I add a datasource like the one below nothing is shown in the child grid but the header.

    01..DataSource(dataSource => dataSource
    02.    .Ajax()
    03.    .ServerOperation(false)
    04.    .Batch(true)
    05.    .Model(model =>
    06.    {
    07.        model.Id(p => p.ID);
    08.    })
    09.)

     

    I also checked these demos

    http://docs.telerik.com/kendo-ui/controls/data-management/grid/how-to/Editing/edit-master-row-data-in-detail-template

    http://www.telerik.com/support/code-library/grid-ajax-hierarchy-editing

    but both use a datasource with .Create() .Read() .Update() .Destroy() operations in the child grid so they're useless to me.

    Is it possible to create the child grid editable without CRUD operations in its datasource?

    Any help will be appreciated.

    PS: I don't even need the Read operation in the datasource because I already have these data!

    Here's my code

    View:

    01.@using TelerikTests.Models
    02.@model TestModel
    03. 
    04.@{
    05.    ViewBag.Title = "Home Page";
    06.}
    07. 
    08.@(Html.Kendo().Grid(Model.Categories)
    09.    .Name("grid_Parent")
    10.    .Columns(columns =>
    11.    {
    12.        columns.Bound(c => c.ID).Hidden();
    13.        columns.Bound(c => c.Description)
    14.            .Width(50);
    15.        columns.Bound(c => c.DateCategory)
    16.            .Format("{0:yyyy/MM/dd}")
    17.            .Width(100);
    18.    })
    19.    .HtmlAttributes(new { style = "height: 380px;" })
    20.    .Scrollable(x => x.Height(300))
    21.    .Sortable(x => x.SortMode(GridSortMode.MultipleColumn))
    22.    .Filterable()
    23.    .DataSource(dataSource => dataSource
    24.        .Ajax()
    25.        .ServerOperation(false)
    26.        .Batch(true)
    27.        .Model(model =>
    28.        {
    29.            model.Id(p => p.ID);
    30.        })
    31.    )
    32.    .ClientDetailTemplateId("child")
    33.    .Events(e => e.DetailInit("childGridInit"))
    34.)
    35. 
    36.<script id="child" type="text/kendo-tmpl">
    37.    @(Html.Kendo().Grid<ProductModel>()
    38.        .Name("gridChild_#=ID#")
    39.        .Columns(columns =>
    40.        {
    41.            columns.Bound(c => c.ID).Hidden();
    42.            columns.Bound(c => c.Name)
    43.                .Width(70);
    44.            columns.Bound(c => c.Price)
    45.                .Width(70);
    46.        })
    47.        //.Editable(x => x.Mode(GridEditMode.InLine))
    48.        //.DataSource(dataSource => dataSource
    49.        //  .Ajax()
    50.        //  .ServerOperation(false)
    51.        //  .Batch(true)
    52.        //  .Model(model =>
    53.        //  {
    54.        //      model.Id(p => p.ID);
    55.        //  })
    56.        //)
    57.        .ToClientTemplate()
    58.    )
    59.</script>
    60. 
    61.<script>
    62.    function childGridInit(e) {
    63.        var grid = $("#gridChild_" + e.data.ID).data("kendoGrid");
    64.        grid.dataSource.data(e.data.Products);
    65.    }
    66.</script>

     

    The model:

    01.public class TestModel
    02.{
    03.    public IEnumerable<CategoryModel> Categories { get; set; }
    04.}
    05. 
    06.public class CategoryModel
    07.{
    08.    public Guid ID { get; set; }
    09.    public string Description { get; set; }
    10.    public DateTime DateCategory { get; set; }
    11.    public IEnumerable<ProductModel> Products { get; set; }
    12.}
    13. 
    14.public class ProductModel
    15.{
    16.    public Guid ID { get; set; }
    17.    public DateTime DateProduct { get; set; }
    18.    public string Name { get; set; }
    19.    public decimal Price { get; set; }
    20.}

  2. Marin
    Admin
    Marin avatar
    1045 posts

    Posted 20 May Link to this post

    Hi,

    Currently the built-in editing feature of the grid requires a DataSource with .Create(), Update() and Delete() methods defined. They are automatically called when you click the "Update", "Cancel" or "Save Changes" buttons in the grid - that's why the grid needs these methods and a model with ID field defined so it knows how to handle the editing.
    The recommended way to achieve this kind of editing is shown in the demos and help articles you referenced in your previous post.

    Regards,
    Marin
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  3. UI for ASP.NET MVC is VS 2017 Ready
  4. Denlys
    Denlys avatar
    6 posts
    Member since:
    May 2016

    Posted 23 May in reply to Marin Link to this post

    Hi Marin,

    Currently I'm creating a parallel project where I'm using a grid without any of the CRUD operations you mentioned. The grid is bound to the data in the model so I don't need a Read() method. I'm not using the grid's toolbar so I've a single button to Create/Update/Delete in a way you (Telerik team) posted somewhere (I don't remember now), so I don't need to execute 1 post for each of that operations (3 POST in total). With only one post I do all of them.

    Here's the grid's code

    01.@(Html.Kendo().Grid(Model.Productos)
    02.    .Name("grid_Seleccionar")
    03.    .Columns(columns =>
    04.    {
    05.        columns.Bound(c => c.IdExpedienteProducto).Hidden();
    06.        columns.Command(command => command.Destroy()).Width(110);
    07.        columns.Bound(c => c.ItemCliente)
    08.            .Width(190);
    09.        columns.Bound(c => c.ReferenciaProveedor)
    10.            .Title("Referencia")
    11.            .Width(70);
    12.        columns.Bound(c => c.PrecioCompra)
    13.            .Width(120);
    14.    })
    15.    .HtmlAttributes(new { style = "height: 380px; width: 200px;" })
    16.    .Scrollable(x => x.Height(300))
    17.    .Sortable(x => x.SortMode(GridSortMode.MultipleColumn))
    18.    .Filterable()
    19.    .Editable(editable => editable.Mode(GridEditMode.InCell))
    20.    .DataSource(dataSource => dataSource
    21.        .Ajax()
    22.        .ServerOperation(false)
    23.        .Batch(true)
    24.        .Model(model =>
    25.        {
    26.            model.Id(p => p.IdExpedienteProducto);
    27.        })
    28.    )
    29.)

    Here's the code of the button (outside the grid) to do the post

    01._public_.gridCreateDataCRUD = function(grid) {
    02.    //get the new and the updated records
    03.    var currentData = grid.dataSource.data();
    04.    var updatedRecords = [];
    05.    var newRecords = [];
    06. 
    07.    for (var i = 0; i < currentData.length; i++) {
    08.        if (currentData[i].isNew()) {
    09.            //this record is new
    10.            newRecords.push(currentData[i].toJSON());
    11.        }
    12.        if (!currentData[i].isNew() && currentData[i].dirty) {
    13.            //this record is updated
    14.            updatedRecords.push(currentData[i].toJSON());
    15.        }
    16.    }
    17. 
    18.    //this records are deleted
    19.    var deletedRecords = [];
    20.    for (var i = 0; i < grid.dataSource._destroyed.length; i++) {
    21.        deletedRecords.push(grid.dataSource._destroyed[i].toJSON());
    22.    }
    23. 
    24.    //all records are sorted and sanitized
    25. 
    26.    //initialize Serializer
    27.    var serializer = new Serializer();
    28. 
    29.    //prefix all records
    30.    var serializedData = [];
    31.    if (deletedRecords.length > 0) {
    32.        var prefix = "deleted";
    33. 
    34.        serializedData = serializedData.concat(serializer.parameterMap(deletedRecords, prefix));
    35.    }
    36. 
    37.    if (updatedRecords.length > 0) {
    38.        var prefix = "updated";
    39. 
    40.        serializedData = serializedData.concat(serializer.parameterMap(updatedRecords, prefix));
    41.    }
    42. 
    43.    if (newRecords.length > 0) {
    44.        var prefix = "new";
    45. 
    46.        serializedData = serializedData.concat(serializer.parameterMap(newRecords, prefix));
    47.    }
    48. 
    49.    var finalData = serializer.collect(serializedData[0], serializedData[1], serializedData[2]);
    50. 
    51.    //finalData now contains prefixed serialized data like:
    52. 
    53.    //new[0].EmployeeID: 0
    54.    //new[0].OrderDate: "8/1/2012 12:00:00 AM"
    55.    //new[0].OrderDescription: "Order Food"
    56.    //new[0].OrderID: 1
    57.    //updated[1].EmployeeID: 2
    58.    //updated[1].OrderDate: "8/1/2012 12:00:00 AM"
    59.    //updated[1].OrderDescription: "Order Office Materials"
    60.    //updated[1].OrderID: 2
    61. 
    62.    return finalData;
    63.}

    With the button code and a $.Post(...) using the returned data (finalData in line 62) I'm able to create, update and delete the data in the server!

    Now I need to create a grid like this one as a child grid.

    Can you help me with this?

    Thank you

  5. Marin
    Admin
    Marin avatar
    1045 posts

    Posted 25 May Link to this post

    Hi,

    The grid's batch editing feature also makes a single request for all update, insert and delete operations. Your custom approach is also viable in this case. However the child grid also needs a dataSource - the same way you use it in the parent grid and the custom code for the outside button:
    _public_.gridCreateDataCRUD = function(grid) {
    var currentData = grid.dataSource.data(); //the dataSource of the grid is needed here
    var updatedRecords = [];
    var newRecords = [];

    Since you handle the CRUD operations manually - of course you do not need to set .Create(), Update() and Delete() methods in the dataSource in this case. However the child grid needs a way to bind to the data. This happens either through the .Read() method of the dataSource or as you have done in the parent grid: data is directly passed to the constructor of the grid:
    @(Html.Kendo().Grid(Model.Productos)

    That's the reason why nothing is shown in the child grid when you just add DataSource without Read operation - the grid can't retrieve the data.

    As a summary: you can use the custom approach with the outside button but in order for this to work the child grid also has to be databound either by passing the data from the Model in the constructor or through .Read method in the dataSource.

    I hope this helps. Let me know if you have any other questions.

    Regards,
    Marin
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  6. Denlys
    Denlys avatar
    6 posts
    Member since:
    May 2016

    Posted 25 May in reply to Marin Link to this post

    Hi Marin,

    However the child grid needs a way to bind to the data. This happens either through the .Read() method of the dataSource or as you have done in the parent grid: data is directly passed to the constructor of the grid:
    @(Html.Kendo().Grid(Model.Productos)

    In my case I'm binding the data to the children grids in the function detailGridInit(e) in line 62 (see the original post) using the event DetailInit(...) in line 33 of the parent grid

    That's the reason why nothing is shown in the child grid when you just add DataSource without Read operation - the grid can't retrieve the data.

    If I comment the statements .Editable() and .Datasource(...) as you can see in the original post lines between 47 and 56 the data is shown as expected but if I uncomment these lines then I can see the data for an instant and then disappear.

    I don't have idea about why this is happening.

    Here I sent you a demo project that include only the necessary code to reproduce the issue.

    https://www.dropbox.com/s/4z9f062mfxarzuq/TelerikTests.7z?dl=0

    Would you please see what's happening?

    I think this way we will save a lot of time.

    Thank you,

    Denlys.

  7. Marin
    Admin
    Marin avatar
    1045 posts

    Posted 26 May Link to this post

    Hi Denlys,

    Thank you for providing the runnable project. I checked the issue on my side and the reason for the disappearance of the data is that when you have .Datasource(...) specified, the child grid will try to make a request to a Read method, but since this method is not defined - there is no data to bind to the child grid.
    In short: the editing requires a DataSource and the DataSource requires to make a request to a Read method, that's the current setup necessary for the editing feature.

    Regards,
    Marin
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  8. Denlys
    Denlys avatar
    6 posts
    Member since:
    May 2016

    Posted 26 May in reply to Marin Link to this post

    Hi Marin,

    Thank you for taking the time to see the issue.

Back to Top
UI for ASP.NET MVC is VS 2017 Ready