@@ -10,65 +10,84 @@ res_type: kb
1010---
1111
1212## Environment
13+
1314<table >
14- <tbody>
15- <tr>
16- <td>Product</td>
17- <td>Grid for Blazor</td>
18- </tr>
19- </tbody>
15+ <tbody>
16+ <tr>
17+ <td>Product</td>
18+ <td>Grid for Blazor</td>
19+ </tr>
20+ </tbody>
2021</table >
2122
2223## Description
2324
24- This article showcases how to ** Create ** , ** Update ** and ** Delete ** items in both the main and nested Grids in a [ hierarchy] ({%slug components/grid/features/hierarchy%}).
25+ This article shows how to create, update, and delete items in the main (master) and nested (detail) Grids in a [ hierarchy] ({%slug components/grid/features/hierarchy%}).
2526
2627
2728## Solution
2829
29- The [ CRUD operations] ({%slug components/grid/editing/overview%}) are independent from the Hierarchy . Each Grid has it`s own handlers.
30+ The Grid CRUD operations are independent of the hierarchy . Each Grid performs editing separately and has its own handlers.
3031
31- The example below showcases those separate handlers and also how you can get the parent model from the nested grid handlers in case you need information from it - the ` UpdateOrder ` , ` CreateOrder ` and ` DeleteOrder ` handlers are getting the context in order to access the Data from the parent. If you do not need access to the main Grid you should not pass the context through a lambda function.
32+ 1 . [ Configure editing for the main Grid] ({%slug components/grid/editing/overview%}).
33+ 1 . Define a [ ` DetailTemplate ` ] ({%slug components/grid/features/hierarchy%}) and configure the nested Grid inside it, including editing.
34+ 1 . To persist the expanded state of a ` DetailTemplate ` while editing its parent item, override the ` Equals() ` method of the master data item class. This is supported from version ** 5.1.0** .
3235
33- You can set the ` EditMode ` of the nesting grid to either ` Popup ` , ` Inline ` , ` Incell ` . By default it is ` Inline ` .
36+ The example below shows the separate CUD event handlers and also how to get the parent data item in the nested Grid handlers. The ` UpdateOrder ` , ` CreateOrder ` , and ` DeleteOrder ` handlers receive the ` productItem ` in order to access the data item from the parent Grid. If you don't need access to the main Grid's data, don't pass the context through a lambda function .
3437
35- > caption How to do CRUD operations in hierarchy grid - get the parent item from inside the child grid
38+ > caption Implement CRUD operations in a hierarchy Grid
3639
37- ````
38- @* If the data in the nested models is sufficient for your operations, you do not need the lambda functions *@
40+ ```` CSHTML
41+ @* The events in the detail Grid are defined with lambda functions, so that the handler can receive the master product object.
42+ This approach is optional. *@
43+
44+ @* Hierarchy expand persistence during edit requires version 5.1.0 + *@
45+
46+ Grid <code>EditMode</code>:
47+ <TelerikRadioGroup Data="@GridEditModes"
48+ @bind-Value="@GridEditMode"
49+ Layout="@RadioGroupLayout.Horizontal" />
3950
4051<TelerikGrid Data="@GridData"
52+ TItem="@Product"
4153 Pageable="true"
4254 PageSize="10"
4355 Sortable="true"
44- EditMode="GridEditMode.Popup"
56+ EditMode="@GridEditMode"
57+ Navigable="true"
4558 OnUpdate="UpdateProduct"
4659 OnDelete="DeleteProduct"
47- OnCreate="CreateProduct">
60+ OnCreate="CreateProduct"
61+ OnStateInit="@OnProductGridStateInit">
4862 <GridToolBarTemplate>
4963 <GridCommandButton Command="Add" Icon="@SvgIcon.Plus">Add Product</GridCommandButton>
5064 </GridToolBarTemplate>
5165 <GridColumns>
5266 <GridColumn Field=@nameof(Product.ProductName) Title="Product Name" />
5367 <GridColumn Field=@nameof(Product.UnitPrice) Title="Unit Price" />
54- <GridColumn Field=@nameof(Product.UnitsInStock) Title="Units in stock " />
55- <GridColumn Field=@nameof(Product.CreatedAt) Title="Date created " />
68+ <GridColumn Field=@nameof(Product.UnitsInStock) Title="Units in Stock " />
69+ <GridColumn Field=@nameof(Product.CreatedAt) Title="Date Created " />
5670 <GridColumn Field=@nameof(Product.Discontinued) Title="Discontinued" Width="150px" />
57- <GridCommandColumn Width="auto">
58- <GridCommandButton Command="Edit" Icon="@SvgIcon.Pencil">Edit</GridCommandButton>
71+ <GridCommandColumn Width="200px">
72+ @if (GridEditMode != GridEditMode.Incell)
73+ {
74+ <GridCommandButton Command="Edit" Icon="@SvgIcon.Pencil">Edit</GridCommandButton>
75+ <GridCommandButton Command="Save" Icon="@SvgIcon.Save" ShowInEdit="true">Save</GridCommandButton>
76+ <GridCommandButton Command="Cancel" Icon="@SvgIcon.Cancel" ShowInEdit="true">Cancel</GridCommandButton>
77+ }
5978 <GridCommandButton Command="Delete" Icon="@SvgIcon.Trash">Delete</GridCommandButton>
6079 </GridCommandColumn>
6180 </GridColumns>
6281 <DetailTemplate Context="productItem">
6382 @{
64- Product product = productItem as Product;
83+ Product product = ( Product)productItem ;
6584
6685 <TelerikGrid Data="@product.OrderDetails"
67- Height="auto"
6886 Pageable="true"
6987 Sortable="true"
7088 PageSize="5"
71- EditMode="GridEditMode.Popup"
89+ EditMode="@GridEditMode"
90+ Navigable="true"
7291 OnUpdate="@((GridCommandEventArgs args) => UpdateOrder(product, args))"
7392 OnDelete="@((GridCommandEventArgs args) => DeleteOrder(args, product))"
7493 OnCreate="@((GridCommandEventArgs args) => CreateOrder(args, product))">
@@ -80,12 +99,17 @@ You can set the `EditMode` of the nesting grid to either `Popup`, `Inline`, `Inc
8099 <GridColumn Field=@nameof(OrderDetails.UnitPrice) Title="Price" />
81100 <GridColumn Field=@nameof(OrderDetails.Discount) Title="Discount">
82101 <Template Context="order">
83- @(String.Format("{0:0.00}%", (order as OrderDetails).Discount))
102+ @(String.Format("{0:0.00}%", (( OrderDetails)order ).Discount))
84103 </Template>
85104 </GridColumn>
86105 <GridColumn Field=@nameof(OrderDetails.Quantity) Title="Quantity" />
87- <GridCommandColumn Width="auto">
88- <GridCommandButton Command="Edit" Icon="@SvgIcon.Pencil">Edit</GridCommandButton>
106+ <GridCommandColumn>
107+ @if (GridEditMode != GridEditMode.Incell)
108+ {
109+ <GridCommandButton Command="Edit" Icon="@SvgIcon.Pencil">Edit</GridCommandButton>
110+ <GridCommandButton Command="Save" Icon="@SvgIcon.Save" ShowInEdit="true">Save</GridCommandButton>
111+ <GridCommandButton Command="Cancel" Icon="@SvgIcon.Cancel" ShowInEdit="true">Cancel</GridCommandButton>
112+ }
89113 <GridCommandButton Command="Delete" Icon="@SvgIcon.Trash">Delete</GridCommandButton>
90114 </GridCommandColumn>
91115 </GridColumns>
@@ -95,13 +119,13 @@ You can set the `EditMode` of the nesting grid to either `Popup`, `Inline`, `Inc
95119</TelerikGrid>
96120
97121@code {
98- // CUD operations for the main Grid
99- #region CUD operation for the main Grid
122+ #region CUD operations for the main Grid
123+
100124 private void UpdateProduct(GridCommandEventArgs args)
101125 {
102126 // perform actual data source operations here through your service
103127
104- var item = args.Item as Product ;
128+ var item = (Product) args.Item;
105129 var index = GridData.FindIndex(x => x.ProductId == item.ProductId);
106130 if (index != -1)
107131 {
@@ -112,9 +136,9 @@ You can set the `EditMode` of the nesting grid to either `Popup`, `Inline`, `Inc
112136 {
113137 // perform actual data source operations here through your service
114138
115- var item = args.Item as Product ;
139+ var item = (Product) args.Item;
116140
117- item.ProductId = GridData.Count + 1 ;
141+ item.ProductId = ++LastId ;
118142
119143 GridData.Insert(0, item);
120144 item.OrderDetails = GenerateOrderDetails(item);
@@ -124,19 +148,20 @@ You can set the `EditMode` of the nesting grid to either `Popup`, `Inline`, `Inc
124148 {
125149 // perform actual data source operations here through your service
126150
127- var item = args.Item as Product ;
151+ var item = (Product) args.Item;
128152
129153 GridData.Remove(item);
130154 }
131- #endregion
132155
133- //CUD operations for the nested Grid
134- #region CUD operations for the nested Grid
156+ #endregion CUD operations for the main Grid
157+
158+ #region CUD operations for the detail Grid
159+
135160 private void UpdateOrder(Product product, GridCommandEventArgs args)
136161 {
137162 // perform actual data source operations here through your service
138163
139- var item = args.Item as OrderDetails ;
164+ var item = (OrderDetails) args.Item;
140165 var data = product.OrderDetails;
141166 int index = data.FindIndex(x => x.OrderId == item.OrderId);
142167 if (index != -1)
@@ -149,7 +174,7 @@ You can set the `EditMode` of the nesting grid to either `Popup`, `Inline`, `Inc
149174 {
150175 // perform actual data source operations here through your service
151176
152- var item = args.Item as OrderDetails ;
177+ var item = (OrderDetails) args.Item;
153178 var data = product.OrderDetails;
154179
155180 item.OrderId = data.Count + 1;
@@ -161,19 +186,39 @@ You can set the `EditMode` of the nesting grid to either `Popup`, `Inline`, `Inc
161186 {
162187 // perform actual data source operations here through your service
163188
164- var item = args.Item as OrderDetails ;
189+ var item = (OrderDetails) args.Item;
165190 var data = product.OrderDetails;
166191
167192 data.Remove(item);
168193 }
169- #endregion
170194
171- public List<Product> GridData { get; set; }
172- DateTime StartDate = new DateTime(2018, 1, 1);
173- static Random RandomGenerator = new Random();
195+ #endregion CUD operations for the detail Grid
196+
197+ private List<Product> GridData { get; set; } = new();
198+ private DateTime StartDate = new DateTime(2018, 1, 1);
199+ private static Random RandomGenerator = new Random();
200+
201+ #region Product Grid State
202+
203+ private void OnProductGridStateInit(GridStateEventArgs<Product> args)
204+ {
205+ args.GridState.ExpandedItems = GridData.Where(x => x.ProductId == 1).ToList();
206+ }
207+
208+ private GridEditMode GridEditMode { get; set; } = GridEditMode.Inline;
209+
210+ private IEnumerable<GridEditMode> GridEditModes { get; set; } = new List<GridEditMode> {
211+ GridEditMode.Incell,
212+ GridEditMode.Inline,
213+ GridEditMode.Popup
214+ };
215+
216+ #endregion Product Grid State
217+
218+ #region Sample Data and Models
219+
220+ private int LastId { get; set; }
174221
175- //Sample data and models
176- #region Sample data and models
177222 protected override void OnInitialized()
178223 {
179224 GridData = GenerateProducts();
@@ -183,12 +228,12 @@ You can set the `EditMode` of the nesting grid to either `Popup`, `Inline`, `Inc
183228 {
184229 List<Product> products = new List<Product>();
185230
186- for (int i = 1; i <= 100 ; i++)
231+ for (int i = 1; i <= 3 ; i++)
187232 {
188233 var product = new Product()
189234 {
190- ProductId = i ,
191- ProductName = "Product " + i.ToString() ,
235+ ProductId = ++LastId ,
236+ ProductName = $ "Product {LastId}" ,
192237 SupplierId = i,
193238 UnitPrice = (decimal)(i * 3.14),
194239 UnitsInStock = (short)(i * 1),
@@ -210,7 +255,7 @@ You can set the `EditMode` of the nesting grid to either `Popup`, `Inline`, `Inc
210255 double maxDiscount = 0.2;
211256 var orderDetails = new List<OrderDetails>();
212257
213- for (int i = 1; i <= 40 ; i++)
258+ for (int i = 1; i <= 2 ; i++)
214259 {
215260 orderDetails.Add(new OrderDetails()
216261 {
@@ -234,13 +279,26 @@ You can set the `EditMode` of the nesting grid to either `Popup`, `Inline`, `Inc
234279 public class Product
235280 {
236281 public int ProductId { get; set; }
237- public string ProductName { get; set; }
282+ public string ProductName { get; set; } = string.Empty;
238283 public int SupplierId { get; set; }
239284 public decimal UnitPrice { get; set; }
240285 public short UnitsInStock { get; set; }
241286 public bool Discontinued { get; set; }
242287 public DateTime CreatedAt { get; set; }
243- public List<OrderDetails> OrderDetails { get; set; }
288+ public List<OrderDetails> OrderDetails { get; set; } = new();
289+
290+ // Persist Product expand/collapse state during editing
291+ public override bool Equals(object? obj) => Equals(obj as Product);
292+
293+ public bool Equals(Product? obj)
294+ {
295+ return obj != null && obj.ProductId == ProductId;
296+ }
297+
298+ public override int GetHashCode()
299+ {
300+ return base.GetHashCode();
301+ }
244302 }
245303
246304 public class OrderDetails
@@ -251,7 +309,12 @@ You can set the `EditMode` of the nesting grid to either `Popup`, `Inline`, `Inc
251309 public float Discount { get; set; }
252310 public int ProductId { get; set; }
253311 }
254- #endregion
312+
313+ #endregion Sample Data and Models
255314}
256315````
257316
317+ ## See Also
318+
319+ * [ Grid Editing] ({%slug components/grid/editing/overview%})
320+ * [ Grid Hierarchy] ({%slug components/grid/features/hierarchy%})
0 commit comments