modeBar add custom button using python

Hi,

I need to add button in modeBarAddButton ie custom buttom in Modebar config field using python.

Thanks

Hi @surr2025 welcome to the forums.

Up to my knowledge this not possible.

Forum search:

1 Like

Thanks for the quick response.

What if I created Javascript function which will search the modebar and add/append img to it at last.
Then created a hidden button {‘display’:‘none’} and mapped this button id with the button id mention in Javascript function.

I need to call this function once the graph is fully loaded.

How can I call Javascript function (present in html file where plotly app_id is specified) from dash-python?

I don’t know much about JS, but this should be possible. Cientside callbacks for example are written in JS. Have you used the forum search. I am pretty sure that this has been asked before.

Hello @surr2025,

Yes, you can create a custom modebar button via JavaScript.

I use it in my own stuff every now and then.

The easiest way to add it is to use a clientside_callback to trigger it with a settimeout of about 300. You can give it the same class as the other buttons to get some of the same effects as the other buttons.

One nice way to call it is:

app.clientside_callback(
‘’’function to add the button here’’’,
Output(‘mygraph’,’id’),
Input(‘mygraph’,’id’)
)

Two important things, do not prevent_initial_call and on the clientside_callback. You need to return window.dash_clientside.no_update

Let me know if you need more info, but I think you can figure it out from here.

3 Likes

setimeout will execute every 300ms. Can we call JavaScript function only once… After dcc.loading loads all the graph?

No, setTimeout says that you want to wait on the execution of the function for 300ms.

What you are thinking of is setinterval.

I was using graph under children component of dcc.loading…

Once the graph is loaded completely then only I want to call JavaScript function to add custom button to modebar.

The custom button can be added only after the graph is loaded.

Set interval 300ms results calling of JavaScript function after 300ms.

How can I wait to check whether graph is loaded?
By using loading_state or something else?

you should be using setTimeout

setTimeout delays the function call for 300ms.

Is it not possible using loading_state… to check whether graph is loaded or not?

Can you please post what you are trying for the clientside_callback? Including how to trigger it?

And as far as whether or not it is loading, you can try checking out here:

Thanks for the update…

Please checkout below code for your reference.

app.layout = html.Div([
		       dbc.Row([
                    		dcc.Loading(
                        	id="loading",
                        	type="circle",
                       		children= [dcc.Graph(id='graph_id')],
                       		)
        		]),
			 dbc.Button("modebar_button", id="modebar_button", n_clicks=0, style={'display':'none'}),
		    ])


# clientside_callback
app.clientside_callback(
    """
        function add_button_modebar() {
	# javascript code to add button in modebar.
	# id="modebar_button", 
	# onclick event
	# This function needs to call automatically once graph is loaded completely ie id="loading"
	}
    """
    Output('no_output', 'no_output'),
    Input('memory', 'data'),
)

Hi,

setTimeout not working. In my case function got called automatically.

It will not wait to load the graph.

Due to the instant function call, modebar div ie doc.querySelector(“div.modebar-container div”) can’t detected by using javascript function.

Would you please provide sample code to check whether graph is loaded or not? I will pass this parameter to the javascript function.

How are you using setTimeout, can you post your callback?

app.clientside_callback(
    """
        setTimeout(myFunction, 300);

        function myFunction() {
            console.log("Function called")
            doc = window.frames[0].document
            d = doc.querySelector("div.modebar-container div");
            # remaining code to add img button + onClick
        }
    Output('display', 'value'),
    Input('memory', 'data'),

Ok, for setTimeout you need to try this:

SetTimeout(function(){myfunction()},300)

Also, any console errors from it not knowing the function at time of call?

Also, your callbacks need to always return something.

Hi Tested above code also.

same error.
Uncaught TypeError: Cannot read properties of undefined (reading 'document')
Function get executed before graph loaded that why not getting ‘documment’ → Uncaughterror .

Your graph is getting displayed in a iframe?

You need to trigger this upon the id of the graph itself and not memory data.