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

Creating a child grid editable

6 Answers 831 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Denlys
Top achievements
Rank 1
Denlys asked on 19 May 2016, 08:03 PM

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.}

6 Answers, 1 is accepted

Sort by
0
Marin
Telerik team
answered on 20 May 2016, 01:42 PM
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
0
Denlys
Top achievements
Rank 1
answered on 23 May 2016, 06:51 PM

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

0
Marin
Telerik team
answered on 25 May 2016, 08:58 AM
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
0
Denlys
Top achievements
Rank 1
answered on 25 May 2016, 03:18 PM

Hi Marin,

[quote]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)[/quote]

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

[quote]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.[/quote]

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.

0
Marin
Telerik team
answered on 26 May 2016, 10:34 AM
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
0
Denlys
Top achievements
Rank 1
answered on 26 May 2016, 02:43 PM

Hi Marin,

Thank you for taking the time to see the issue.

Tags
Grid
Asked by
Denlys
Top achievements
Rank 1
Answers by
Marin
Telerik team
Denlys
Top achievements
Rank 1
Share this question
or