Hey everyone!
I was wondering if it’s possible to use Patch()
in clientside callbacks? I’m working on a Dash app where I want to highlight part of a figure (with a purple or grey bar) whenever a bar is selected.
The only problem is that the chart flashes, even though I’m using Patch
to try to make the update smoother. Any ideas on how to fix this?
Here’s the code I’m using along with a GIF to show what I mean:
Serverside Callback, which is working:
@dash_app.callback(
Output("bar_chart", "figure", allow_duplicate=True),
Input("bar_chart", "clickData"),
Input("reload-chart", "n_clicks"),
prevent_initial_call=True
)
def draw_on_chart(click, reload):
INDICATOR_TYPE = 'purple' # 'grey'
trigger_id = ctx.triggered_id
patched_figure = Patch()
if trigger_id == 'bar_chart':
patched_figure.layout.shapes.clear()
if INDICATOR_TYPE == 'purple':
x_index_range = (click['points'][0]['pointIndex'] - .3, click['points'][0]['pointIndex'] + .3)
patched_figure.layout.shapes.append({'type': 'rect', 'xref': 'x', 'yref': 'paper', 'x0': x_index_range[0], 'x1': x_index_range[1], 'y0': -0.2, 'y1': -0.22, 'line': {'color': '#6F326A'}, 'fillcolor': '#6F326A', 'opacity': 1})
elif INDICATOR_TYPE == 'grey':
x_index_range = (click['points'][0]['pointIndex'] - .45, click['points'][0]['pointIndex'] + .45)
patched_figure.layout.shapes.append({'type': 'rect', 'xref': 'x', 'yref': 'paper', 'x0': x_index_range[0], 'x1': x_index_range[1], 'y0': -0.02, 'y1': -0.2, 'line': {'color': '#DCDCDC'}, 'fillcolor': '#DCDCDC', 'opacity': 0.3})
elif trigger_id == 'reload-chart':
patched_figure.layout.shapes.clear()
else:
return no_update
return patched_figure
Clientside Callback, which didn’t worked:
dash_app.clientside_callback(
"""
function(clickData, n_clicks) {
let INDICATOR_TYPE = 'grey';
let patchedFigure = { layout: { shapes: [] } };
let trigger_id = dash_clientside.callback_context.triggered[0].prop_id;
console.log(trigger_id);
if (trigger_id === "bar_chart.clickData") {
if (clickData && clickData.points && clickData.points.length > 0) {
const pointIndex = clickData.points[0].pointIndex;
patchedFigure.layout.shapes = []; // Clear existing shapes
if (INDICATOR_TYPE === 'purple') {
let x_index_range = [pointIndex - 0.3, pointIndex + 0.3];
patchedFigure.layout.shapes.push({
type: 'rect',
xref: 'x',
yref: 'paper',
x0: x_index_range[0],
x1: x_index_range[1],
y0: -0.2,
y1: -0.22,
line: { color: '#6F326A' },
fillcolor: '#6F326A',
opacity: 1
});
} else if (INDICATOR_TYPE === 'grey') {
let x_index_range = [pointIndex - 0.45, pointIndex + 0.45];
patchedFigure.layout.shapes.push({
type: 'rect',
xref: 'x',
yref: 'paper',
x0: x_index_range[0],
x1: x_index_range[1],
y0: -0.02,
y1: -0.2,
line: { color: '#DCDCDC' },
fillcolor: '#DCDCDC',
opacity: 0.3
});
}
}
} else if (trigger_id === "reload-chart.n_clicks") {
patchedFigure.layout.shapes = []; // Clear shapes
}
return patchedFigure;
}
""",
Output("bar_chart", "figure", allow_duplicate=True),
[Input("bar_chart", "clickData"),
Input("reload-chart", "n_clicks")],
prevent_initial_call=True
)
Thanks for your patience