We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date
close icon

TreeView - Context Menus

I have a TreeView which I'm generating by looping over my model. I have three levels of the tree, and I want each level to have a different right click context menu, but all items in the same level to have the same options.

I can sort of get this working by having a different div id for each level of the tree and assigning a different menu to it, however it only works for the first node for each level.

Lets say i have the following tree:

Products (id="productContext")
 - Mens (id="categoryContext")
    - Polo Shirts (id="itemContext")
 - Womens (id="categoryContext")
    - Dresses (id="itemContext")

And I have created the menu for each of the contexts like the example below

<ul id="itemMenu">
    <li>
        <a>Create New Item</a>
    </li>
    <li>
        <a>Delete Item</a>
    </li>
</ul>

And I apply the menu to the correct Divs

@{Html.Syncfusion().Menu("itemMenu").Mode(MenuModel.ModeType.ContextMenu).ContextMenuTargetId("itemContext").ClientSideOnContextOpen("OnContextOpen").Render();}

The issue is that the right click context menu will only show if I right click the first item node in the tree.

This is due to the fact that all of the items will have the same ID

So to get around this I add the item ID to the element ID like so:

 <li><img src="~/Images/ItemNode.png" /><a id="itemContext_@(item.Item_ID)"> @(item.Item_NAME)</a></li>

and also create a loop around the context menu to apply it for all nodes:

@foreach (item in category)
{
      Html.Syncfusion().Menu("itemMenu").Mode(MenuModel.ModeType.ContextMenu).ContextMenuTargetId("itemContext_" + item.Item_ID).ClientSideOnContextOpen("OnContextOpen").Render();
}

But this just generates the same html for each node:

<div id="itemMenu_sfMenuContainer" name="itemMenu" tabindex="100"></div>
<div id="itemMenu_sfMenuContainer" name="itemMenu" tabindex="100"></div>
<div id="itemMenu_sfMenuContainer" name="itemMenu" tabindex="100"></div>

Is there any way to get the context menu to apply to all items of the same class instead of id?

Another example would be a file tree where you want to have the same context menu for the folders, but each file may have different options depending on file type.

Any assistance is appreciated,

Regards, Laszlo


8 Replies

GA Gurunathan A Syncfusion Team August 1, 2013 01:45 PM UTC

Hi Laszlo

Thanks for contacting Syncfusion

Your requirement of using different context menu in different level of TreeView Control can be achieved by setting the id for ul of particular level in TreeView ClientSideOnLoaded event and then assign this id as Context menu target id. Please refer the following code snippet.

<code>

[.cshtml]

@{Html.Syncfusion().TreeView("myTreeView", new { @class = "style" })

            .ShowLines(true)

            .AllowEdit(true)

            .Width(300)

            .Height(460)

            .DataSource((System.Collections.IEnumerable)ViewData["TreeViewData"])

            .BindTo(fields => fields

                .Id("ID")

                .ParentId("ParentID")

                .Text("MenuText")

                ).ClientSideOnLoaded("onload").Render();}

<ul id="myMenu1">

    <li> <a>Cut</a></li>

    <li> <a>Copy</a></li>

    <li> <a>Paste</a></li>

 

</ul>

    @*--Menu Helper1--*@

  @{ Html.Syncfusion().Menu("myMenu1").Mode(MenuModel.ModeType.ContextMenu).ContextMenuTargetId("myTreeView_DataBinding").Render(); }

  <ul id="myMenu2">

    <li> <a>Add</a></li>

    <li> <a>Remove</a></li>

  </ul>

    @*--Menu Helper2--*@

  @{ Html.Syncfusion().Menu("myMenu2").Mode(MenuModel.ModeType.ContextMenu).ContextMenuTargetId("level1").Render(); }

  <ul id="myMenu3">

    <li> <a>childnode Add</a></li>

    <li> <a>Child node Remove</a></li>

  </ul>

    @*--Menu Helper3--*@

  @{ Html.Syncfusion().Menu("myMenu3").Mode(MenuModel.ModeType.ContextMenu).ContextMenuTargetId("level2").Render(); }

<script type ="text/javascript" >

          function onload() {

              $("#1").children("ul").attr("id", "level1");

              $("#4").children("ul").attr("id", "level2");

           }

</script>

 </code>

Note: Currently we do not provide Context Menu with ContextTargetid as Class Name.

We have prepared a sample to show case this behavior. It can be downloaded from given below link

Tree_Contextmenu.zip

Kindly check the sample, let us know if it helps.

Warm Regards,

Gurunathan



LB Laszlo Boross August 2, 2013 03:15 AM UTC

Ahh, thanks! The problem was that I was applying the ID to the <LI> tags and not the <UL> tags. I have it working now. 

Just one follow up, is there a way to make it so only a single context menu is shown at a time. Please refer to the attached screenshot where I am able to open each of the context menus simultaneously.




ContextMenu01_21de65f2.zip


GA Gurunathan A Syncfusion Team August 12, 2013 11:13 AM UTC

Hi Laszlo,

Thanks for contacting Syncfusion support.

Since, we are using different ContextMenu's for each level, the ContextMenu opened previously was not hidden when a new ContextMenu is opened. So, can you please manually hide the context menus which is opened previously before opening a new ContextMenu? Please refer the below given code snippet to resolve this issue,

<code>

[view]

@{ Html.Syncfusion().Menu("myMenu1").Mode(MenuModel.ModeType.ContextMenu).ContextMenuTargetId("myTreeView_DataBinding").ClientSideOnBeforeContextOpen("closemenu").Render(); }

 

@{ Html.Syncfusion().Menu("myMenu2").Mode(MenuModel.ModeType.ContextMenu).ContextMenuTargetId("level1").ClientSideOnBeforeContextOpen("closemenu1").Render(); }

 

@{ Html.Syncfusion().Menu("myMenu3").Mode(MenuModel.ModeType.ContextMenu).ContextMenuTargetId("level2").ClientSideOnBeforeContextOpen("closemenu2").Render(); }

<script type ="text/javascript" >

         

          function closemenu2()

          {

              $find("myMenu1").HideContextMenu();

              $find("myMenu2").HideContextMenu();

          }

          function closemenu1() {

              $find("myMenu1").HideContextMenu();

              $find("myMenu3").HideContextMenu();

          }

          function closemenu() {

              $find("myMenu3").HideContextMenu();

              $find("myMenu2").HideContextMenu();

          }

</script>

</code>

 

We have prepared a simple sample to exhibit this behavior. It can be downloaded from given below link.

Tree_Contextmenu.zip

Kindly check the sample, let us know if you have further queries.

Warm Regards,

Gurunathan



RL RL February 7, 2015 12:58 PM UTC

I came across this thread looking for something similar to this.
So let me leave here some example of setting the contenxtmenu depending on an attribute of the node:

$("#menuEmployees").ejMenu({
                menuType: ej.MenuType.ContextMenu,
                openOnClick: false,
                contextMenuTarget: "li[data-nodetype='employee']",
                click: "menuclick",
                beforeOpen: "beforeOpen"
            });


RL RL replied to RL February 7, 2015 01:22 PM UTC

I came across this thread looking for something similar to this.
So let me leave here some example of setting the contenxtmenu depending on an attribute of the node:

$("#menuEmployees").ejMenu({
                menuType: ej.MenuType.ContextMenu,
                openOnClick: false,
                contextMenuTarget: "li[data-nodetype='employee']",
                click: "menuclick",
                beforeOpen: "beforeOpen"
            });

If you have more than one level you may see more than 1 menu.

Just ensure that the outer menu only shows if a certain condition is present, if not in the before open use the args.cancel.

function beforeDepartmentsOpen(args) {
        if ($(args.target.parentElement.parentElement).data("nodetype") !== 'department') {
            args.cancel = true;
        }
    }

This works quite fine for me this way, hope it helps others.


HP Harikrishnan P Syncfusion Team February 9, 2015 12:43 PM UTC

Hi Rui,

Thanks for updating an example to showcase ‘how to set up a context menu in Treeview based on particular attribute in a node’.

We would also like to let you know that, the target for the context menu can also be a class instead of ID. So, we can apply context menu to many elements having same class. We have attached a simple sample in the following location to showcase this.

Sample Location: context menu using class

Please let us know if you have any queries.

Regards,

HariKrishnan




RL RL February 9, 2015 08:28 PM UTC

Great stuff! For my particular case I stick with the custom attribute I need it in another part of my application.
But the basic idea here is to show that the target is actually any kind of string that can be used as a JQuery selector. I think this is something that you should change in the documentation, just say in the docs that we can use any kind of jquery selector expression.




HP Harikrishnan P Syncfusion Team February 11, 2015 03:51 AM UTC

Hi Rui,

Query: But the basic idea here is to show that the target is actually any kind of string that can be used as a JQuery selector. I think this is something that you should change in the documentation, just say in the docs that we can use any kind of jquery selector expression.

Thanks for pointing about the correction that we have to do in our documentation, regarding the description of ‘contextMenuTarget’ API. As you have mentioned, we can use any kind of string as a JQuery selector for setting the target of context menu. We will make this correction in our documentations and will also refresh it in our online JS API reference link.

Please let us know if you have further queries.

Regards,

HariKrishnan



Loader.
Up arrow icon