Skip to content

Commit dbd971e

Browse files
chore(contextMenu): separate integration article
1 parent 445008a commit dbd971e

File tree

3 files changed

+392
-361
lines changed

3 files changed

+392
-361
lines changed

components/contextmenu/integration.md

Lines changed: 389 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,389 @@
1+
---
2+
title: Integration
3+
page_title: Context Menu - Integration
4+
description: Integrating the context menu with other code and customizing it according to the target and its metadata.
5+
slug: contextmenu-integration
6+
tags: telerik,blazor,menu,integration
7+
published: True
8+
position: 3
9+
---
10+
11+
# Context Menu Integration
12+
13+
In some cases, you may need to know which element the user clicked so you can use it in the command handling. You may also want to adjust the menu contents based on which element the user clicked (e.g., disable or entirely remove some items from the menu based on a condition).
14+
15+
Using the `Selector` parameter to attach the context menu to one or more targets at a time is simple, and can be useful when you want the same menu for many elements, but it does not matter which one the user clicked. So, the Telerik Context Menu offers the `ShowAsync(x, y)` method that lets you show it on demand after executing business logic.
16+
17+
To achieve such flexibility and granularity, you can:
18+
19+
1. Use your own code to hook to an event such as `@oncontextmenu` to store the desired target and its metadata.
20+
* You can use other events to show the context menu, like click, mousedown and so on. Make sure to pass correct coordinates to the menu - they must be relative to the viewport.
21+
* If you use the `@oncontextmenu` event, also add `@oncontextmenu:preventDefault="true"` to avoid the browser context menu which will always show above HTML structures on the page, like the Telerik Context Menu.
22+
1. Optionally, alter the [data source]({%slug contextmenu-data-binding-overview%}) or [templates]({%slug contextmenu-templates-overview%}) of the menu based on the metadata for the target.
23+
1. Show the Telerik menu through its `@ref` and the `ShowAsync` method it exposes.
24+
25+
This article provides the following two examples:
26+
27+
28+
* [Know The Target And Adjust Items](#know-the-target-and-adjust-items)
29+
* [Context Menu for a Grid Row](#context-menu-for-a-grid-row)
30+
31+
## Know The Target And Adjust Items
32+
33+
Hooking to your own HTML elements' events lets you determine what to do with the context menu before showing it (for example, altering its data source).
34+
35+
>caption Use the context menu target and change menu items based on the target data
36+
37+
````CSHTML
38+
@* Get context menu target and alter its items based on it *@
39+
40+
<TelerikContextMenu Data="@MenuItems" @ref="@TheContextMenu"
41+
TextField="Text" SeparatorField="Separator" IconField="Icon" DisabledField="Disabled"
42+
OnClick="@( (ContextMenuItem itm) => ClickHandler(itm) )">
43+
</TelerikContextMenu>
44+
45+
<TelerikListView Data="@ListViewData" Width="700px" Pageable="true">
46+
<Template>
47+
<div @oncontextmenu:preventDefault="true"
48+
@oncontextmenu="@( (MouseEventArgs e) => ShowContextMenu(e, context) )"
49+
class="listview-item">
50+
<h4>@context.Name</h4>
51+
<h5>@context.Team</h5>
52+
<h6>Special context menu: @context.IsSpecial</h6>
53+
</div>
54+
</Template>
55+
</TelerikListView>
56+
57+
@code {
58+
public List<ContextMenuItem> MenuItems { get; set; }
59+
TelerikContextMenu<ContextMenuItem> TheContextMenu { get; set; }
60+
SampleData LastClickedItem { get; set; }
61+
62+
async Task ShowContextMenu(MouseEventArgs e, SampleData clickedItem)
63+
{
64+
// save the target/metadata
65+
LastClickedItem = clickedItem;
66+
// change the menu items
67+
PrepareMenuItems(clickedItem);
68+
// show the menu
69+
await TheContextMenu.ShowAsync(e.ClientX, e.ClientY);
70+
}
71+
72+
void PrepareMenuItems(SampleData clickedItem)
73+
{
74+
// disable one item, you can make bigger changes here too
75+
MenuItems[2].Items[0].Disabled = clickedItem.IsSpecial;
76+
}
77+
78+
async Task ClickHandler(ContextMenuItem clickedItem)
79+
{
80+
// handle the command from the context menu by using the stored metadata
81+
if (!string.IsNullOrEmpty(clickedItem.CommandName) && LastClickedItem != null)
82+
{
83+
Console.WriteLine($"The programm will now perform the {clickedItem.CommandName} operation for {LastClickedItem.Name}");
84+
}
85+
LastClickedItem = null;
86+
}
87+
88+
// generate sample data for the listview and the menu
89+
protected override void OnInitialized()
90+
{
91+
92+
MenuItems = new List<ContextMenuItem>()
93+
{
94+
new ContextMenuItem
95+
{
96+
Text = "More Info",
97+
Icon = IconName.Information,
98+
CommandName = "info"
99+
},
100+
new ContextMenuItem
101+
{
102+
Separator = true
103+
},
104+
new ContextMenuItem
105+
{
106+
Text = "Advanced",
107+
Items = new List<ContextMenuItem>()
108+
{
109+
new ContextMenuItem
110+
{
111+
Text = "Delete",
112+
Icon = IconName.Delete,
113+
CommandName = "delete"
114+
},
115+
new ContextMenuItem
116+
{
117+
Text = "Report",
118+
Icon = IconName.Cancel,
119+
CommandName = "report"
120+
}
121+
}
122+
}
123+
};
124+
125+
base.OnInitialized();
126+
}
127+
128+
public class ContextMenuItem
129+
{
130+
public string Text { get; set; }
131+
public string CommandName { get; set; }
132+
public string Icon { get; set; }
133+
public bool Separator { get; set; }
134+
public bool Disabled { get; set; }
135+
public List<ContextMenuItem> Items { get; set; }
136+
}
137+
138+
List<SampleData> ListViewData { get; set; } = Enumerable.Range(1, 25).Select(x => new SampleData
139+
{
140+
Id = x,
141+
Name = $"Name {x}",
142+
Team = $"Team {x % 3}",
143+
IsSpecial = x % 4 == 0
144+
}).ToList();
145+
146+
public class SampleData
147+
{
148+
public int Id { get; set; }
149+
public string Name { get; set; }
150+
public string Team { get; set; }
151+
public bool IsSpecial { get; set; }
152+
}
153+
}
154+
155+
<style>
156+
.listview-item {
157+
height: 150px;
158+
width: 150px;
159+
display: inline-block;
160+
margin: 10px;
161+
border: 1px solid black;
162+
border-radius: 10px;
163+
padding: 10px;
164+
}
165+
</style>
166+
````
167+
168+
## Context Menu for a Grid Row
169+
170+
To integrate the context menu with the Telerik Grid, you need to:
171+
172+
1. Use the grid's `OnRowContextMenu` event to get the current row model and show the menu
173+
2. Use the context menu's `OnClick` event to handle the desired operation
174+
175+
In this example, the context menu is used to select/deselect items, put an item in edit mode and delete items
176+
177+
>caption Use a Context Menu for Grid rows
178+
179+
````CSHTML
180+
@using System.Collections.Generic
181+
@using System.Collections.ObjectModel
182+
183+
<TelerikContextMenu @ref="@ContextMenuRef" Data="@MenuItems" OnClick="@((MenuItem item) => OnItemClick(item))"></TelerikContextMenu>
184+
185+
<TelerikGrid Data="@GridData" @ref="@GridRef"
186+
EditMode="@GridEditMode.Inline"
187+
Height="500px"
188+
Pageable="true"
189+
OnCreate="@CreateItem" OnUpdate="@UpdateHandler"
190+
OnRowContextMenu="@OnContextMenu"
191+
SelectionMode="@GridSelectionMode.Multiple"
192+
@bind-SelectedItems="@SelectedItems">
193+
<GridToolBar>
194+
<GridCommandButton Command="Add" Icon="add">Add Employee</GridCommandButton>
195+
</GridToolBar>
196+
<GridColumns>
197+
<GridColumn Field=@nameof(SampleData.ID) Editable="false" />
198+
<GridColumn Field=@nameof(SampleData.Name) />
199+
<GridCommandColumn>
200+
<GridCommandButton Command="Save" Icon="save" ShowInEdit="true">Update</GridCommandButton>
201+
<GridCommandButton Command="Cancel" Icon="cancel" ShowInEdit="true">Cancel</GridCommandButton>
202+
</GridCommandColumn>
203+
</GridColumns>
204+
</TelerikGrid>
205+
206+
@if (SelectedItems.Any())
207+
{
208+
<ul>
209+
@foreach (var item in SelectedItems)
210+
{
211+
<li>@item.Name</li>
212+
}
213+
</ul>
214+
}
215+
216+
@code {
217+
//data sources
218+
ObservableCollection<SampleData> GridData { get; set; }
219+
List<MenuItem> MenuItems { get; set; }
220+
IEnumerable<SampleData> SelectedItems { get; set; } = Enumerable.Empty<SampleData>();
221+
//metadata for the context menu actions
222+
SampleData SelectedPerson { get; set; }
223+
//component references so we can use their methods
224+
TelerikContextMenu<MenuItem> ContextMenuRef { get; set; }
225+
TelerikGrid<SampleData> GridRef { get; set; }
226+
227+
// sample menu item class
228+
public class MenuItem
229+
{
230+
public string Text { get; set; }
231+
public string Icon { get; set; }
232+
public Action Action { get; set; }
233+
public string CommandName { get; set; }
234+
}
235+
236+
// show the context menu for a particular row
237+
async Task OnContextMenu(GridRowClickEventArgs args)
238+
{
239+
var argsItem = args.Item as SampleData;
240+
241+
SelectedPerson = argsItem;
242+
243+
if (args.EventArgs is MouseEventArgs mouseEventArgs)
244+
{
245+
await ContextMenuRef.ShowAsync(mouseEventArgs.ClientX, mouseEventArgs.ClientY);
246+
}
247+
}
248+
249+
// sample handling of the context menu click
250+
async Task OnItemClick(MenuItem item)
251+
{
252+
// one way to pass handlers is to use an Action, you don't have to use this
253+
if (item.Action != null)
254+
{
255+
item.Action.Invoke();
256+
}
257+
else
258+
{
259+
// or you can use local code to perform a task
260+
// such as put a row in edit mode or select it
261+
switch (item.CommandName)
262+
{
263+
case "BeginEdit": // read more at https://localhost/blazor-ui/components/grid/state#initiate-editing-or-inserting-of-an-item
264+
var currState = GridRef.GetState();
265+
currState.InsertedItem = null;
266+
SampleData itemToEdit = SampleData.GetClonedInstance(GridData.Where(itm => itm.ID == SelectedPerson.ID).FirstOrDefault());
267+
currState.OriginalEditItem = itemToEdit;
268+
await GridRef.SetState(currState);
269+
break;
270+
case "ToggleSelect":
271+
var selItems = SelectedItems.ToList();
272+
if (SelectedItems.Contains(SelectedPerson))
273+
{
274+
selItems.Remove(SelectedPerson);
275+
}
276+
else
277+
{
278+
selItems.Add(SelectedPerson);
279+
}
280+
SelectedItems = selItems;
281+
break;
282+
default:
283+
break;
284+
}
285+
}
286+
SelectedPerson = null; // clean up
287+
}
288+
289+
// generate data
290+
protected override void OnInitialized()
291+
{
292+
// context menu items
293+
MenuItems = new List<MenuItem>()
294+
{
295+
new MenuItem(){ Text = "Select", Icon=IconName.CheckboxChecked, CommandName="ToggleSelect" },
296+
new MenuItem(){ Text = "Edit", Icon=IconName.Edit, CommandName="BeginEdit" },
297+
new MenuItem(){ Text = "Delete", Icon=IconName.Delete, Action = DeleteItem }
298+
};
299+
300+
// generate data for the grid
301+
GridData = new ObservableCollection<SampleData>();
302+
var rand = new Random();
303+
304+
for (int i = 0; i < 100; i++)
305+
{
306+
GridData.Add(new SampleData()
307+
{
308+
ID = i,
309+
Name = "Employee " + i.ToString(),
310+
});
311+
}
312+
}
313+
314+
315+
// CUD operations for the grid
316+
317+
async Task CreateItem(GridCommandEventArgs args)
318+
{
319+
var argsItem = args.Item as SampleData;
320+
321+
// call the actual data service here
322+
323+
argsItem.ID = GridData.Count + 1;
324+
325+
GridData.Insert(0, argsItem);
326+
}
327+
328+
void DeleteItem() // not async so it can be passed as an Action
329+
{
330+
var argsItem = SelectedPerson;
331+
332+
// call the actual data service here
333+
334+
GridData.Remove(argsItem);
335+
}
336+
337+
async Task UpdateHandler(GridCommandEventArgs args)
338+
{
339+
var argsItem = args.Item as SampleData;
340+
341+
// call the actual data service here
342+
343+
var index = GridData.ToList().FindIndex(i => i.ID == argsItem.ID);
344+
if (index != -1)
345+
{
346+
GridData[index] = argsItem;
347+
}
348+
}
349+
350+
public class SampleData
351+
{
352+
public int ID { get; set; }
353+
public string Name { get; set; }
354+
355+
356+
public override bool Equals(object obj)
357+
{
358+
if (obj is SampleData)
359+
{
360+
return this.ID == (obj as SampleData).ID;
361+
}
362+
return false;
363+
}
364+
365+
public SampleData()
366+
{
367+
368+
}
369+
370+
public SampleData(SampleData itmToClone)
371+
{
372+
this.ID = itmToClone.ID;
373+
this.Name = itmToClone.Name;
374+
}
375+
376+
public static SampleData GetClonedInstance(SampleData itmToClone)
377+
{
378+
return new SampleData(itmToClone);
379+
}
380+
}
381+
}
382+
````
383+
384+
385+
## See Also
386+
387+
* [Context Menu Overview]({%slug contextmenu-overview%})
388+
* [Context Menu Data Binding]({%slug contextmenu-data-binding-overview%})
389+
* [Context Menu Templates]({%slug contextmenu-templates-overview%})

components/contextmenu/navigation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: Using the Blazor Context Menu for navigating between pages.
55
slug: contextmenu-navigation
66
tags: telerik,blazor,menu,navigation
77
published: True
8-
position: 3
8+
position: 10
99
---
1010

1111
# Context Menu for Navigation

0 commit comments

Comments
 (0)