# Right-click custom context menu

**URL:** <https://community.plotly.com/t/right-click-custom-context-menu/76954>\
**Category:** Dash Python\
**Created:** [July 17, 2023, 1:48pm UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954 "2023-07-17T13:48:06Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sank95](https://avatars.discourse-cdn.com/v4/letter/s/8edcca/32.png) [@Sank95](https://community.plotly.com/u/Sank95)\
**Post date:** [July 17, 2023, 1:48pm UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/1 "2023-07-17T13:48:06Z")

</div>

HI guys. I need to call event Right-click and open context menu. How do you do it?

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [July 17, 2023, 2:58pm UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/2 "2023-07-17T14:58:30Z")

</div>

Hello @Sank95,

Welcome to the community!

Assuming you know some JS, you just add the event listener to your component upon load.

The easiest way is to do this through a clientside callback:

```auto
app.clientside_callback(
"""function (id) {
    document.getElementById(id).addEventListener('contextmenu', myfunc())
    window.dash_clientside.no_update
}""", Output('component', 'id'), Input('component', 'id')
)

```

You can have your custom function in the assets folder in a js file and this will auto load.

---

<div class="post-metadata">

**Author:** ![hadikhamoud](https://avatars.discourse-cdn.com/v4/letter/h/f07891/32.png) [@hadikhamoud](https://community.plotly.com/u/hadikhamoud)\
**Post date:** [July 19, 2023, 9:12am UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/4 "2023-07-19T09:12:54Z")

</div>

Hello, how are you!

Following up on this question. What’s the easiest way to trigger a callback from a right-click context menu event.

Thanks!

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [July 19, 2023, 10:21am UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/5 "2023-07-19T10:21:15Z")

</div>

You can have dash components inside the div, on right click you just toggle the location and the display of the div.

So, you’d have to use position absolute and then give it the left and top of the event.clientX and event.clientY.

There might also be some better components that you could use that might be able do some of this labor for you.

---

<div class="post-metadata">

**Author:** ![CNFeffery](https://avatars.discourse-cdn.com/v4/letter/c/d07c76/32.png) [@CNFeffery](https://community.plotly.com/u/CNFeffery)\
**Post date:** [July 19, 2023, 1:23pm UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/6 "2023-07-19T13:23:11Z")

</div>

@Sank95 You can follow this demo, very advanced context menu:

[https://fac.feffery.tech/AntdDropdown#自由位置模式](https://fac.feffery.tech/AntdDropdown#%E8%87%AA%E7%94%B1%E4%BD%8D%E7%BD%AE%E6%A8%A1%E5%BC%8F)

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [July 19, 2023, 2:31pm UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/7 "2023-07-19T14:31:35Z")

</div>

Hello @CNFeffery,

This is a cool component indeed. Unfortunately, it requires your target components to be something that exposes the contextMenu event, like your div.

Using a JS event listener allows for any component to be used.

There are a couple of tricks that we can use with components that are already available from Dash.

---

<div class="post-metadata">

**Author:** ![CNFeffery](https://avatars.discourse-cdn.com/v4/letter/c/d07c76/32.png) [@CNFeffery](https://community.plotly.com/u/CNFeffery)\
**Post date:** [July 19, 2023, 2:43pm UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/8 "2023-07-19T14:43:20Z")

</div>

`fuc.FefferyDiv` could be used as any target’s container, for example, as the root container of the whole page, then creating a right-click menu anywhere will be as easy as drinking water.

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [July 19, 2023, 2:45pm UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/9 "2023-07-19T14:45:05Z")

</div>

How would you determine the event target for multiple components?

Wrap each and every one of the components inside the div?

---

<div class="post-metadata">

**Author:** ![CNFeffery](https://avatars.discourse-cdn.com/v4/letter/c/d07c76/32.png) [@CNFeffery](https://community.plotly.com/u/CNFeffery)\
**Post date:** [July 19, 2023, 3:01pm UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/10 "2023-07-19T15:01:12Z")

</div>

if the `isHovering` of `FefferyDiv` is `True`, then we can be sure that the right-click event occurred in the target container.

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [July 19, 2023, 3:07pm UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/11 "2023-07-19T15:07:09Z")

</div>

Yes, you can tell that it occurred in the div container from the `contextMenu`.

But, you cant wrap two components like such with just one listener:

```auto
fef.FefferDiv([
    dcc.Input(id='1'), dcc.Input(id='2')
])

```

And have both components have different context menus.

In JS you can switch as such:

```auto
if (event.target.id == '1') { return context1 }
if (event.target.id == '2') { return context2 }

```

---

<div class="post-metadata">

**Author:** ![CNFeffery](https://avatars.discourse-cdn.com/v4/letter/c/d07c76/32.png) [@CNFeffery](https://community.plotly.com/u/CNFeffery)\
**Post date:** [July 19, 2023, 3:16pm UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/12 "2023-07-19T15:16:47Z")

</div>

indeed, it’s pretty easy, without any javascript (by the way, I think dash’s core competency is that there is no need or little to write javascript, otherwise, why Dash):

![图5](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/b/8/b879aa12a89c8d78a89a53df5948e70b91c7af3f.gif)

```bash
import dash
import json
from dash import html, dcc
import feffery_utils_components as fuc
from dash.dependencies import Input, Output

app = dash.Dash( __name__ )

app.layout = html.Div(
    [
        html.Div(
            [
                fuc.FefferyDiv(
                    dcc.Input(
                        placeholder='input1'
                    ),
                    id='wrap-input1',
                    enableListenContextMenu=True,
                    style={
                        'display': 'inline'
                    }
                ),
                fuc.FefferyDiv(
                    dcc.Input(
                        placeholder='input2'
                    ),
                    id='wrap-input2',
                    enableListenContextMenu=True,
                    style={
                        'display': 'inline'
                    }
                )
            ]
        ),
        html.Pre(id='event-output')
    ],
    style={
        'padding': 50
    }
)

@app.callback(
    Output('event-output', 'children'),
    [Input('wrap-input1', 'contextMenuEvent'),
     Input('wrap-input2', 'contextMenuEvent')]
)
def show_event(contextMenuEvent1, contextMenuEvent2):

    return json.dumps(
        {
            'who trigger?': dash.ctx.triggered_id,
            'event': contextMenuEvent1 if dash.ctx.triggered_id == 'wrap-input1' else contextMenuEvent2
        },
        indent=4
    )

if __name__ == ' __main__':
    app.run(debug=True)

```

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [July 19, 2023, 3:25pm UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/13 "2023-07-19T15:25:08Z")

</div>

Writing an event listener is pretty straightforward, and well within scope of creating a custom context menu.

Yes, I am aware that you could wrap individual event listeners, the way that you just did.

---

<div class="post-metadata">

**Author:** ![CNFeffery](https://avatars.discourse-cdn.com/v4/letter/c/d07c76/32.png) [@CNFeffery](https://community.plotly.com/u/CNFeffery)\
**Post date:** [July 19, 2023, 3:28pm UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/14 "2023-07-19T15:28:13Z")

</div>

I think the callback function in dash is a very genius design, which is both simple and versatile. If combined with a large number of functional components that can be implemented without javascript, dash will be favored by more python users. It’s way ahead of weird-conceptually confusing frameworks like streamlit, gradio, reflex, etc

---

<div class="post-metadata">

**Author:** ![Sank95](https://avatars.discourse-cdn.com/v4/letter/s/8edcca/32.png) [@Sank95](https://community.plotly.com/u/Sank95)\
**Post date:** [July 21, 2023, 9:03am UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/16 "2023-07-21T09:03:40Z")

</div>

Hi guys. So, I want to show MRE. I want to clarify the task. I need call contextmenu for AntTree and want to know id clicked element and selected element in contextmeny.

```auto
from dash import dcc, html, dash_table, Input, Output, State, callback, clientside_callback, Patch
import dash_draggable
import pandas as pd
import dash
import feffery_antd_components as fac

app = dash.Dash( __name__ )

app.layout = html.Div([
    dcc.Location(id="url"),
    dash_draggable.ResponsiveGridLayout(
        id='tests',
        clearSavedLayout=True,
        height=100,
        resizeHandles=["e"],
        compactType="horizontal",
        verticalCompact=False,

        layouts={
            "lg": [{
                "i": "tree_programming",
                "x": 0, "y": 0, "w": 2, "h": 7.5,
                "minW": 1, "maxW": 2

            },
                {
                    "i": "output_area",
                    "x": 2, "y": 0, "w": 10, "h": 7.5,
                    "minW": 6, "maxW": 10
                }
            ],
        },

        children=[
            html.Div(
                id='tree_programming',
            ),
            html.Div(
                id='output_area',
                children=[
                    dcc.Tabs(
                        id="tabs",
                        value='main',
                        children=[
                            dcc.Tab(
                                label="Default",
                                value='output_default',
                                id="output_default"
                            ),

                            dcc.Tab(
                                label="Show datasets",
                                value="area7",
                                id='output_flex'
                            )
                        ]
                    )
                ]
            ),
        ]
    )
])

@callback(
    [
        Output('tree_programming', 'children')
    ],
    [
        Input("url", 'pathname'),
        Input("url", 'search')
    ]
)
def create_tree(path, search):
    df_scope = pd.DataFrame({'x': [123, 42, 4235, 523, 35235, 523, 253], 'y': [12, 523, 53, 523, 5235235, 523, 1]})

    children_dataset = [{'title': i, 'key': 'key_' + i} for i in df_scope.columns]
    layout_tree = create_layout_tree(children_dataset)
    return [layout_tree]

def create_layout_tree(children_dataset):
    layout_tree = fac.AntdTree(
        id='tree_geomechanic',
        treeData=[
            {
                'title': 'Dataset',
                'key': 'dataset',
                'selectable': False,
                'children': [
                    {
                        'title': 'Dataset',
                        'key': 'df',
                        'children': children_dataset
                    },
                ]
            },
        ],
        multiple=True,
        height=600,
    )
    return layout_tree

if __name__ == ' __main__':
    #waitress.serve(server, listen='0.0.0.0:8080', threads=24)
    app.run_server(debug=False, host='127.0.0.1', port=83, threaded=True)

```

---

<div class="post-metadata">

**Author:** ![CNFeffery](https://avatars.discourse-cdn.com/v4/letter/c/d07c76/32.png) [@CNFeffery](https://community.plotly.com/u/CNFeffery)\
**Post date:** [July 23, 2023, 11:21am UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/17 "2023-07-23T11:21:49Z")

</div>

AntdTree has the built-in function of right-clicking nodes.

![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/0/a/0ae1f16b6c32f6d7ed893f83a1e6185a52cf0cef.png)

[https://fac.feffery.tech/AntdTree#节点右键菜单回调示例](https://fac.feffery.tech/AntdTree#%E8%8A%82%E7%82%B9%E5%8F%B3%E9%94%AE%E8%8F%9C%E5%8D%95%E5%9B%9E%E8%B0%83%E7%A4%BA%E4%BE%8B)

---

<div class="post-metadata">

**Author:** ![Sank95](https://avatars.discourse-cdn.com/v4/letter/s/8edcca/32.png) [@Sank95](https://community.plotly.com/u/Sank95)\
**Post date:** [July 24, 2023, 9:26am UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/18 "2023-07-24T09:26:07Z")

</div>

This answer solved the problem

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [August 30, 2023, 7:48pm UTC](https://community.plotly.com/t/right-click-custom-context-menu/76954/19 "2023-08-30T19:48:12Z")

</div>

A post was split to a new topic: [Context Menu on Cytoscape](https://community.plotly.com/t/context-menu-on-cytoscape/78171)
