Skip to content

Commit 236b629

Browse files
kendo-botKB Bot
andauthored
Added new kb article grid-expand-edited-row (#3146)
Co-authored-by: KB Bot <[email protected]>
1 parent 89b33f6 commit 236b629

File tree

1 file changed

+287
-0
lines changed

1 file changed

+287
-0
lines changed
Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
---
2+
title: How to Automatically Expand the Currently Edited Row
3+
description: Learn how to automatically expand the detail of the currently edited or newly inserted item in the TelerikGrid for UI for Blazor.
4+
type: how-to
5+
page_title: Expanding Details of Edited or New Row in TelerikGrid
6+
meta_title: Expanding Details of Edited or New Row in TelerikGrid
7+
slug: grid-kb-expand-edited-row
8+
tags: grid, expand, template, edit, mode, hierarchy
9+
res_type: kb
10+
ticketid: 1694649
11+
---
12+
13+
## Environment
14+
<table>
15+
<tbody>
16+
<tr>
17+
<td>Product</td>
18+
<td>Grid for Blazor</td>
19+
</tr>
20+
</tbody>
21+
</table>
22+
23+
## Description
24+
25+
I want to automatically expand the detail template of the row that is currently being edited or the newly inserted item in the [TelerikGrid](slug:grid-overview).
26+
27+
## Solution
28+
29+
To achieve automatic expansion of a detail template for the edited or newly inserted item, use the `OnEdit` and `OnCreate` events of the TelerikGrid with the `SetStateAsync` method. Below is an example implementation:
30+
31+
>caption Expand currently edited row
32+
33+
````RAZOR
34+
<TelerikGrid @ref="@GridRef"
35+
Data="@GridData"
36+
TItem="@Product"
37+
Pageable="true"
38+
PageSize="10"
39+
Sortable="true"
40+
EditMode="@GridEditMode"
41+
Navigable="true"
42+
OnUpdate="UpdateProduct"
43+
OnDelete="DeleteProduct"
44+
OnCreate="CreateProduct"
45+
OnEdit="@OnEdit"
46+
OnStateInit="@OnProductGridStateInit">
47+
<GridToolBarTemplate>
48+
<GridCommandButton Command="Add" Icon="@SvgIcon.Plus">Add Product</GridCommandButton>
49+
</GridToolBarTemplate>
50+
<GridColumns>
51+
<GridColumn Field=@nameof(Product.ProductName) Title="Product Name" />
52+
<GridColumn Field=@nameof(Product.UnitPrice) Title="Unit Price" />
53+
<GridColumn Field=@nameof(Product.UnitsInStock) Title="Units in Stock" />
54+
<GridColumn Field=@nameof(Product.CreatedAt) Title="Date Created" />
55+
<GridColumn Field=@nameof(Product.Discontinued) Title="Discontinued" Width="150px" />
56+
<GridCommandColumn Width="200px">
57+
@if (GridEditMode != GridEditMode.Incell)
58+
{
59+
<GridCommandButton Command="Edit" Icon="@SvgIcon.Pencil">Edit</GridCommandButton>
60+
<GridCommandButton Command="Save" Icon="@SvgIcon.Save" ShowInEdit="true">Save</GridCommandButton>
61+
<GridCommandButton Command="Cancel" Icon="@SvgIcon.Cancel" ShowInEdit="true">Cancel</GridCommandButton>
62+
}
63+
<GridCommandButton Command="Delete" Icon="@SvgIcon.Trash">Delete</GridCommandButton>
64+
</GridCommandColumn>
65+
</GridColumns>
66+
67+
<DetailTemplate Context="productItem">
68+
@{
69+
Product product = (Product)productItem;
70+
<TelerikGrid Data="@product.OrderDetails"
71+
Pageable="true"
72+
Sortable="true"
73+
PageSize="5"
74+
EditMode="@GridEditMode"
75+
Navigable="true"
76+
OnUpdate="@((GridCommandEventArgs args) => UpdateOrder(product, args))"
77+
OnDelete="@((GridCommandEventArgs args) => DeleteOrder(args, product))"
78+
OnCreate="@((GridCommandEventArgs args) => CreateOrder(args, product))">
79+
<GridToolBarTemplate>
80+
<GridCommandButton Command="Add" Icon="@SvgIcon.Plus">Add Order</GridCommandButton>
81+
</GridToolBarTemplate>
82+
<GridColumns>
83+
<GridColumn Field=@nameof(OrderDetails.OrderId) Title="Order ID" Editable="false" />
84+
<GridColumn Field=@nameof(OrderDetails.UnitPrice) Title="Price" />
85+
<GridColumn Field=@nameof(OrderDetails.Discount) Title="Discount">
86+
<Template Context="order">
87+
@(String.Format("{0:0.00}%", ((OrderDetails)order).Discount))
88+
</Template>
89+
</GridColumn>
90+
<GridColumn Field=@nameof(OrderDetails.Quantity) Title="Quantity" />
91+
<GridCommandColumn>
92+
@if (GridEditMode != GridEditMode.Incell)
93+
{
94+
<GridCommandButton Command="Edit" Icon="@SvgIcon.Pencil">Edit</GridCommandButton>
95+
<GridCommandButton Command="Save" Icon="@SvgIcon.Save" ShowInEdit="true">Save</GridCommandButton>
96+
<GridCommandButton Command="Cancel" Icon="@SvgIcon.Cancel" ShowInEdit="true">Cancel</GridCommandButton>
97+
}
98+
<GridCommandButton Command="Delete" Icon="@SvgIcon.Trash">Delete</GridCommandButton>
99+
</GridCommandColumn>
100+
</GridColumns>
101+
</TelerikGrid>
102+
}
103+
</DetailTemplate>
104+
</TelerikGrid>
105+
106+
@code {
107+
public TelerikGrid<Product> GridRef { get; set; }
108+
109+
private GridEditMode GridEditMode { get; set; } = GridEditMode.Inline;
110+
private List<Product> GridData { get; set; } = new();
111+
private int LastId { get; set; }
112+
private DateTime StartDate = new DateTime(2018, 1, 1);
113+
private static Random RandomGenerator = new Random();
114+
115+
// When a row enters edit mode, expand it
116+
private async Task OnEdit(GridCommandEventArgs args)
117+
{
118+
var editedItem = (Product)args.Item;
119+
120+
var state = GridRef.GetState();
121+
state.ExpandedItems = new List<Product> { editedItem }; // collapse all others
122+
await GridRef.SetStateAsync(state);
123+
}
124+
125+
#region CRUD Operations for Main Grid
126+
private void UpdateProduct(GridCommandEventArgs args)
127+
{
128+
var item = (Product)args.Item;
129+
var index = GridData.FindIndex(x => x.ProductId == item.ProductId);
130+
if (index != -1)
131+
{
132+
GridData[index] = item;
133+
}
134+
}
135+
136+
private void CreateProduct(GridCommandEventArgs args)
137+
{
138+
var item = (Product)args.Item;
139+
item.ProductId = ++LastId;
140+
GridData.Insert(0, item);
141+
item.OrderDetails = GenerateOrderDetails(item);
142+
143+
// Auto-expand the new item
144+
_ = ExpandNewItem(item);
145+
}
146+
147+
private async Task ExpandNewItem(Product newItem)
148+
{
149+
await Task.Delay(50); // ensure grid state has updated
150+
var state = GridRef.GetState();
151+
state.ExpandedItems = new List<Product> { newItem };
152+
await GridRef.SetStateAsync(state);
153+
}
154+
155+
private void DeleteProduct(GridCommandEventArgs args)
156+
{
157+
var item = (Product)args.Item;
158+
GridData.Remove(item);
159+
}
160+
#endregion
161+
162+
#region CRUD for Details Grid
163+
private void UpdateOrder(Product product, GridCommandEventArgs args)
164+
{
165+
var item = (OrderDetails)args.Item;
166+
var data = product.OrderDetails;
167+
int index = data.FindIndex(x => x.OrderId == item.OrderId);
168+
if (index != -1)
169+
{
170+
data[index] = item;
171+
}
172+
}
173+
174+
private void CreateOrder(GridCommandEventArgs args, Product product)
175+
{
176+
var item = (OrderDetails)args.Item;
177+
var data = product.OrderDetails;
178+
item.OrderId = data.Count + 1;
179+
data.Insert(0, item);
180+
}
181+
182+
private void DeleteOrder(GridCommandEventArgs args, Product product)
183+
{
184+
var item = (OrderDetails)args.Item;
185+
var data = product.OrderDetails;
186+
data.Remove(item);
187+
}
188+
#endregion
189+
190+
private void OnProductGridStateInit(GridStateEventArgs<Product> args)
191+
{
192+
args.GridState.ExpandedItems = new List<Product>(); // start with nothing expanded
193+
}
194+
195+
#region Data Generation
196+
protected override void OnInitialized()
197+
{
198+
GridData = GenerateProducts();
199+
}
200+
201+
private List<Product> GenerateProducts()
202+
{
203+
List<Product> products = new List<Product>();
204+
205+
for (int i = 1; i <= 3; i++)
206+
{
207+
var product = new Product()
208+
{
209+
ProductId = ++LastId,
210+
ProductName = $"Product {LastId}",
211+
SupplierId = i,
212+
UnitPrice = (decimal)(i * 3.14),
213+
UnitsInStock = (short)(i * 1),
214+
Discontinued = RandomGenerator.NextDouble() >= 0.5,
215+
CreatedAt = GetRandomDate(StartDate)
216+
};
217+
218+
product.OrderDetails = GenerateOrderDetails(product);
219+
products.Add(product);
220+
}
221+
222+
return products;
223+
}
224+
225+
private List<OrderDetails> GenerateOrderDetails(Product product)
226+
{
227+
double minDiscount = 0.1;
228+
double maxDiscount = 0.2;
229+
var orderDetails = new List<OrderDetails>();
230+
231+
for (int i = 1; i <= 2; i++)
232+
{
233+
orderDetails.Add(new OrderDetails()
234+
{
235+
OrderId = Int32.Parse($"{product.ProductId}{i}"),
236+
UnitPrice = (decimal)product.UnitPrice,
237+
Quantity = (short)(1 + (RandomGenerator.Next() % 10)),
238+
Discount = (float)((RandomGenerator.NextDouble() * (maxDiscount - minDiscount) + minDiscount)) * 100,
239+
ProductId = product.ProductId,
240+
});
241+
}
242+
243+
return orderDetails;
244+
}
245+
246+
private DateTime GetRandomDate(DateTime startDate)
247+
{
248+
int range = (DateTime.Today - startDate).Days;
249+
return startDate.AddDays(RandomGenerator.Next(range));
250+
}
251+
#endregion
252+
253+
#region Models
254+
public class Product
255+
{
256+
public int ProductId { get; set; }
257+
public string ProductName { get; set; } = string.Empty;
258+
public int SupplierId { get; set; }
259+
public decimal UnitPrice { get; set; }
260+
public short UnitsInStock { get; set; }
261+
public bool Discontinued { get; set; }
262+
public DateTime CreatedAt { get; set; }
263+
public List<OrderDetails> OrderDetails { get; set; } = new();
264+
265+
// Ensures Grid can identify which rows are expanded
266+
public override bool Equals(object? obj) => Equals(obj as Product);
267+
public bool Equals(Product? obj) => obj != null && obj.ProductId == ProductId;
268+
public override int GetHashCode() => ProductId.GetHashCode();
269+
}
270+
271+
public class OrderDetails
272+
{
273+
public int OrderId { get; set; }
274+
public decimal UnitPrice { get; set; }
275+
public short Quantity { get; set; }
276+
public float Discount { get; set; }
277+
public int ProductId { get; set; }
278+
}
279+
#endregion
280+
}
281+
````
282+
283+
## See Also
284+
285+
* [Grid Overview](slug:grid-overview)
286+
* [SetStateAsync Method](slug:grid-state#methods)
287+
* [Hierarchical Grid](slug:components/grid/features/hierarchy)

0 commit comments

Comments
 (0)