Skip to content

Commit 49d1933

Browse files
github-actions[bot]KB Botxristianstefanov
authored
Merge new-kb-grid-kb-loader-during-contextmenu-actions-465c440840c94328913eeb780e9e6d3a-2717 into production (#2727)
* Added new kb article grid-kb-loader-during-contextmenu-actions * chore(Grid): address comments * chore(Grid): address latest comments * chore(Grid): return delay * chore(Grid): remove delete action as per last comment --------- Co-authored-by: KB Bot <kb-bot@telerik.com> Co-authored-by: Hristian Stefanov <Hristian.Stefanov@progress.com>
1 parent 2733637 commit 49d1933

File tree

1 file changed

+231
-0
lines changed

1 file changed

+231
-0
lines changed
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
---
2+
title: Display Loader During ContextMenu Actions in Grid
3+
description: Learn how to show a loading indicator while performing actions from a ContextMenu in a Telerik Grid for Blazor.
4+
type: how-to
5+
page_title: How to Display a Loader in TelerikGrid for Blazor During ContextMenu Actions
6+
slug: grid-kb-loader-during-contextmenu-actions
7+
tags: contextmenu, grid, loader, loading, loadercontainer
8+
res_type: kb
9+
ticketid: 1675767
10+
---
11+
12+
## Environment
13+
14+
<table>
15+
<tbody>
16+
<tr>
17+
<td>Product</td>
18+
<td>Grid for Blazor</td>
19+
<td>Context Menu for Blazor</td>
20+
</tr>
21+
</tbody>
22+
</table>
23+
24+
## Description
25+
26+
When the TelerikGrid is used with ContextMenu for various row actions, there is a noticeable delay between selecting an action and its execution. This delay could be due to data retrieval or data manipulation. The goal is to display a loading notice to the user while the data loads and the result is not yet visible.
27+
28+
This knowledge base article also answers the following questions:
29+
- How to use the TelerikLoaderContainer during data fetch operations in Blazor?
30+
- How to show a loading indicator while waiting for an action?
31+
- How to improve user experience during delayed operations in TelerikGrid with ContextMenu in Blazor?
32+
33+
## Solution
34+
35+
To display a spinner during delayed operations initiated from a ContextMenu in a TelerikGrid, utilize the [TelerikLoaderContainer](slug://loadercontainer-overview) component. Display the TelerikLoaderContainer while the data is being loaded or an action is being performed, and hide it once the operation is complete.
36+
37+
````RAZOR
38+
@using System.Collections.ObjectModel
39+
40+
<TelerikContextMenu @ref="@ContextMenuRef" Data="@MenuItems"
41+
OnClick="@((MenuItem item) => ContextMenuClickHandler(item))">
42+
</TelerikContextMenu>
43+
44+
<TelerikLoaderContainer Visible="@LoaderVisible" Text="Please wait..." />
45+
46+
<TelerikGrid Data="@GridData" @ref="@GridRef"
47+
EditMode="@GridEditMode.Inline"
48+
Height="500px"
49+
Pageable="true"
50+
OnCreate="@CreateItem" OnUpdate="@UpdateHandler"
51+
OnRowContextMenu="@OnContextMenu"
52+
SelectionMode="@GridSelectionMode.Multiple"
53+
@bind-SelectedItems="@SelectedItems">
54+
<GridToolBarTemplate>
55+
<GridCommandButton Command="Add" Icon="@SvgIcon.Plus">Add Employee</GridCommandButton>
56+
</GridToolBarTemplate>
57+
<GridColumns>
58+
<GridColumn Field=@nameof(SampleData.ID) Editable="false" />
59+
<GridColumn Field=@nameof(SampleData.Name) />
60+
<GridCommandColumn>
61+
<GridCommandButton Command="Save" Icon="@SvgIcon.Save" ShowInEdit="true">Save</GridCommandButton>
62+
<GridCommandButton Command="Cancel" Icon="@SvgIcon.Cancel" ShowInEdit="true">Cancel</GridCommandButton>
63+
</GridCommandColumn>
64+
</GridColumns>
65+
</TelerikGrid>
66+
67+
@if (SelectedItems.Any())
68+
{
69+
<ul>
70+
@foreach (var item in SelectedItems)
71+
{
72+
<li>@item.Name</li>
73+
}
74+
</ul>
75+
}
76+
77+
@code {
78+
private ObservableCollection<SampleData> GridData { get; set; }
79+
private List<MenuItem> MenuItems { get; set; }
80+
private IEnumerable<SampleData> SelectedItems { get; set; } = Enumerable.Empty<SampleData>();
81+
private SampleData SelectedPerson { get; set; }
82+
private TelerikContextMenu<MenuItem> ContextMenuRef { get; set; }
83+
private TelerikGrid<SampleData> GridRef { get; set; }
84+
private bool LoaderVisible { get; set; }
85+
86+
public class MenuItem
87+
{
88+
public string Text { get; set; }
89+
public ISvgIcon Icon { get; set; }
90+
public Action Action { get; set; }
91+
public string CommandName { get; set; }
92+
}
93+
94+
private async Task OnContextMenu(GridRowClickEventArgs args)
95+
{
96+
var argsItem = args.Item as SampleData;
97+
98+
SelectedPerson = argsItem;
99+
100+
if (args.EventArgs is MouseEventArgs mouseEventArgs)
101+
{
102+
await ContextMenuRef.ShowAsync(mouseEventArgs.ClientX, mouseEventArgs.ClientY);
103+
}
104+
}
105+
106+
private async Task ContextMenuClickHandler(MenuItem item)
107+
{
108+
if (item.Action != null)
109+
{
110+
item.Action.Invoke();
111+
}
112+
else
113+
{
114+
switch (item.CommandName)
115+
{
116+
case "BeginEdit":
117+
LoaderVisible = true;
118+
await Task.Delay(1); // triggers UI refresh for the LoaderContainer to show
119+
await Task.Delay(3000); // replace with the actual long-running task
120+
LoaderVisible = false;
121+
122+
var currState = GridRef.GetState();
123+
currState.InsertedItem = null;
124+
SampleData itemToEdit = SampleData.GetClonedInstance(GridData.Where(itm => itm.ID == SelectedPerson.ID).FirstOrDefault());
125+
currState.OriginalEditItem = itemToEdit;
126+
await GridRef.SetStateAsync(currState);
127+
break;
128+
case "ToggleSelect":
129+
LoaderVisible = true;
130+
await Task.Delay(1); // triggers UI refresh for the LoaderContainer to show
131+
await Task.Delay(3000); // replace with the actual long-running task
132+
LoaderVisible = false;
133+
134+
var selItems = SelectedItems.ToList();
135+
if (SelectedItems.Contains(SelectedPerson))
136+
{
137+
selItems.Remove(SelectedPerson);
138+
}
139+
else
140+
{
141+
selItems.Add(SelectedPerson);
142+
}
143+
SelectedItems = selItems;
144+
break;
145+
default:
146+
break;
147+
}
148+
}
149+
SelectedPerson = null; // clean up
150+
}
151+
152+
protected override void OnInitialized()
153+
{
154+
MenuItems = new List<MenuItem>()
155+
{
156+
new MenuItem(){ Text = "Select", Icon = SvgIcon.CheckboxChecked, CommandName="ToggleSelect" },
157+
new MenuItem(){ Text = "Edit", Icon = SvgIcon.Pencil, CommandName="BeginEdit" }
158+
};
159+
160+
GridData = new ObservableCollection<SampleData>();
161+
var rand = new Random();
162+
163+
for (int i = 1; i < 100; i++)
164+
{
165+
GridData.Add(new SampleData()
166+
{
167+
ID = i,
168+
Name = "Employee " + i.ToString(),
169+
});
170+
}
171+
}
172+
173+
private async Task CreateItem(GridCommandEventArgs args)
174+
{
175+
var argsItem = args.Item as SampleData;
176+
177+
argsItem.ID = GridData.Count + 1;
178+
179+
GridData.Insert(0, argsItem);
180+
}
181+
182+
private async Task UpdateHandler(GridCommandEventArgs args)
183+
{
184+
var argsItem = args.Item as SampleData;
185+
186+
var index = GridData.ToList().FindIndex(i => i.ID == argsItem.ID);
187+
if (index != -1)
188+
{
189+
GridData[index] = argsItem;
190+
}
191+
}
192+
193+
public class SampleData
194+
{
195+
public int ID { get; set; }
196+
public string Name { get; set; }
197+
198+
199+
public override bool Equals(object obj)
200+
{
201+
if (obj is SampleData)
202+
{
203+
return this.ID == (obj as SampleData).ID;
204+
}
205+
return false;
206+
}
207+
208+
public SampleData()
209+
{
210+
211+
}
212+
213+
public SampleData(SampleData itmToClone)
214+
{
215+
this.ID = itmToClone.ID;
216+
this.Name = itmToClone.Name;
217+
}
218+
219+
public static SampleData GetClonedInstance(SampleData itmToClone)
220+
{
221+
return new SampleData(itmToClone);
222+
}
223+
}
224+
}
225+
````
226+
227+
## See Also
228+
229+
* [LoaderContainer Overview](slug://loadercontainer-overview)
230+
* [Grid Overview](slug://grid-overview)
231+
* [ContextMenu Overview](slug://contextmenu-overview)

0 commit comments

Comments
 (0)