I’m trying to run a function that does a simple task (like truncating the legends titles after 5 letters) after the graph is loaded or changed. So far I managed to do with a clientside_callback
this by waiting 500ms before applying the truncation. In my real application however is very hard to predict how long to wait, because it depends on the user input. Therefore it would be better to wait until the div graph is fully loaded.
I tried to
- set up a
eventListener
- work with
plotly_afterplot
- with
window.onload()
- or with a
MutationObserver
but all three did not work. They all could not “wait long enough” it seemed. Either way, the graph div was still null
or div id="graph" class="dash-graph dash-graph--pending"
, meaning loaded asynchronously and still pending.
Is there a way to achieve this? It would be preferable to have it done without the need of importing the entire d3 or plotly library.
This is my only working, but not very elegant or robust solution with clientside_callback
and fixed waiting time:
from dash import Dash, html, dcc, callback, clientside_callback, ClientsideFunction
from dash.dependencies import Input, Output, State
import dash_bootstrap_components as dbc
import plotly.express as px
df = px.data.iris()
app = Dash(__name__)
app.layout = html.Div([
dbc.Button('change', id='btn-change'),
dcc.Graph(id='graph',
style={'width': '100vw', 'height': '80vh'},
figure=px.scatter(df,
x='sepal_width', y='sepal_length', color='species')),
])
clientside_callback(
ClientsideFunction(
namespace='clientside',
function_name='trunc_legend_titles'
),
Output('graph', 'id'),
Input('graph', 'figure'),
)
@callback(
Output('graph', 'figure'),
Input('btn-change', 'n_clicks'),
)
def change_graph(n_clicks):
return px.scatter(df, x='petal_width', y='petal_length', color='species')
if __name__ == '__main__':
app.run_server(debug=True)
window.dash_clientside = Object.assign({}, window.dash_clientside, {
clientside: {
trunc_legend_titles: function(figure) {
setTimeout(function() {
var legendItems = document.querySelectorAll('.legendtext');
legendItems.forEach(function(item) {
var name = item.textContent;
var truncatedName = name.length > 5 ? name.substring(0, 5) + '...' : name;
item.textContent = truncatedName;
});
}, 500); // Wait for the plot to be fully rendered
return window.dash_clientside.no_update
}
}
});