5.2 KiB
title | description | type | page_title | slug | position | tags | ticketid | res_type |
---|---|---|---|---|---|---|---|---|
Add ContextMenu to the TreeView items | How add ContextMenu to the TreeView items. | how-to | Add ContextMenu to the TreeView items | contextmenu-kb-treeview-item | 1508692 | kb |
Environment
Product | ContextMenu for Blazor, TreeView for Blazor |
Description
I would like to add the ContextMenu component to every item (node) in the TreeView.
Solution
The ContextMenu exposes an API to associate the component to any DOM element through the [ShowAsync]({%slug contextmenu-integration%}) method. You can use the oncontextmenu event of an HTML element in the [treeview item template]({%slug components/treeview/templates%}) to show the context menu by using the MouseEventArgs
.
tip As of version 2.27, the TreeView exposes [
OnItemContextMenu
event]({%slug treeview-events%}#onitemcontextmenu) that you can use to integrate Telerik Context menu for the TreeView nodes. Here is an example of such a configuration - [Context menu for a TreeView node]({%slug contextmenu-integration%}#context-menu-for-a-treeview-node)
@* Use the oncontextmenu event of the HTML element to show the ContextMenu for the TreeView items *@
<TelerikContextMenu Data="@ContextMenuData"
@ref="ContextMenu"
SeparatorField="Separator"
TextField="Text"
IconField="Icon"
OnClick="@((ContextMenuItem item) => ClickHandler(item))">
</TelerikContextMenu>
<TelerikTreeView Data="@TreeData">
<TreeViewBindings>
<TreeViewBinding>
<ItemTemplate>
@{
TreeItem itm = context as TreeItem;
<div @oncontextmenu:preventDefault="true"
@oncontextmenu="@((MouseEventArgs e) => ShowContextMenu(e, itm))">
Node:
<strong>@itm.Text</strong>
</div>
}
</ItemTemplate>
</TreeViewBinding>
</TreeViewBindings>
</TelerikTreeView>
@code {
private TelerikContextMenu<ContextMenuItem> ContextMenu { get; set; }
TreeItem LastClickedItem { get; set; }
private async Task ShowContextMenu(MouseEventArgs e, TreeItem item)
{
LastClickedItem = item;
await ContextMenu.ShowAsync(e.ClientX, e.ClientY);
}
private void ClickHandler(ContextMenuItem item)
{
if (!string.IsNullOrEmpty(item.Text) && LastClickedItem != null)
{
Console.WriteLine($"Clicked on {item.CommandName} for {LastClickedItem.Text}");
}
LastClickedItem = null;
}
async Task NodeClick(TreeItem clickeNode)
{
//custom code here
}
// sample data
public IEnumerable<TreeItem> TreeData { get; set; }
public List<ContextMenuItem> ContextMenuData { get; set; }
public class ContextMenuItem
{
public string Text { get; set; }
public ISvgIcon Icon { get; set; }
public bool Separator { get; set; }
public string CommandName { get; set; }
}
public class TreeItem
{
public string Text { get; set; }
public int Id { get; set; }
public List<TreeItem> Items { get; set; } = new List<TreeItem>();
public bool Expanded { get; set; }
public bool HasChildren { get; set; }
}
protected override void OnInitialized()
{
LoadHierarchical();
ContextMenuData = new List<ContextMenuItem>()
{
new ContextMenuItem
{
Text = "Info",
Icon = SvgIcon.InfoCircle,
CommandName = "info"
},
new ContextMenuItem
{
Separator = true
},
new ContextMenuItem
{
Text = "Delete",
Icon = SvgIcon.Trash,
CommandName = "delete"
}
};
}
private void LoadHierarchical()
{
List<TreeItem> roots = new List<TreeItem>() {
new TreeItem { Text = "Item 1", Id = 1, Expanded = true, HasChildren = true },
new TreeItem { Text = "Item 2", Id = 2, HasChildren = true }
};
roots[0].Items.Add(new TreeItem
{
Text = "Item 1 first child",
Id = 3
});
roots[0].Items.Add(new TreeItem
{
Text = "Item 1 second child",
Id = 4
});
roots[1].Items.Add(new TreeItem
{
Text = "Item 2 first child",
Id = 5
});
roots[1].Items.Add(new TreeItem
{
Text = "Item 2 second child",
Id = 6
});
TreeData = roots;
}
}
Notes
At the time of writing, when you are using a template you cannot trigger a close of the ContextMenu, you can only close it if you click outside of it (there is an opened feature request for that in our public feedback portal) that contains a workaround.