New to Telerik UI for Blazor? Download free 30-day trial

Add ContextMenu to the TreeView items

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 method. You can use the oncontextmenu event of an HTML element in the treeview item template to show the context menu by using the MouseEventArgs.

As of version 2.27, the TreeView exposes OnItemContextMenu event 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

@* 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.

In this article