Hi Wander,
Here’s the layout to make the similar-looking buttons:
def get_graph_in_div(is_rt, graph_id):
cn = "mr-1 mb-1 py-0 px-1"
st = {"font-size": "0.8em"}
cl = "secondary"
div_body = []
# A place to put a message, such as "no data available for this unit"
div_body.append(html.Div(id=f"{graph_id}_msg"))
# For the real time chart, make a custom set of rangeselector buttons
# since the chart is constantly refreshing and not remembering the selected range
if is_rt:
div_body.append(
html.Div(
[
dcc.Store(id="store_rt_rangeselector", storage_type="session"),
dbc.Button(
"1m",
id="rt_rng_btn_1",
color=cl,
className=cn + " offset-1",
style=st,
),
dbc.Button(
"2m", id="rt_rng_btn_2", color=cl, className=cn, style=st
),
dbc.Button(
"5m", id="rt_rng_btn_3", color=cl, className=cn, style=st
),
dbc.Button(
"10m", id="rt_rng_btn_4", color=cl, className=cn, style=st
),
dbc.Button(
"20m", id="rt_rng_btn_5", color=cl, className=cn, style=st
),
dbc.Button(
"1h", id="rt_rng_btn_6", color=cl, className=cn, style=st
),
dbc.Button(
"all", id="rt_rng_btn_7", color=cl, className=cn, style=st
),
],
className="player text-left",
id=f"{graph_id}_rangeselector_buttons",
)
)
# Now add the actual graph, whose figure will be updated with a callback
div_body.append(
dcc.Graph(
id=graph_id,
# Disable the ModeBar with the Plotly logo and other buttons
config=dict(
displayModeBar=False,
),
style={"display": "none"},
),
)
return html.Div(div_body)
and here are the callbacks:
@dash_app.callback(
Output("store_rt_rangeselector", "data"),
[
Input("rt_rng_btn_1", "n_clicks"),
Input("rt_rng_btn_2", "n_clicks"),
Input("rt_rng_btn_3", "n_clicks"),
Input("rt_rng_btn_4", "n_clicks"),
Input("rt_rng_btn_5", "n_clicks"),
Input("rt_rng_btn_6", "n_clicks"),
Input("rt_rng_btn_7", "n_clicks"),
],
)
def store_rt_rangeselector_value(_1, _2, _3, _4, _5, _6, _7):
"""Store which real time chart rangeselector button has been clicked"""
# Find which id in the inputs has been triggered
ctx = dash.callback_context
if ctx.triggered:
id_triggered = ctx.triggered[0]["prop_id"].split(".")[0]
else:
raise dash.exceptions.PreventUpdate
data = {}
if id_triggered == "rt_rng_btn_1":
data = {"time_delta": "1 minutes"}
elif id_triggered == "rt_rng_btn_2":
data = {"time_delta": "2 minutes"}
elif id_triggered == "rt_rng_btn_3":
data = {"time_delta": "5 minutes"}
elif id_triggered == "rt_rng_btn_4":
data = {"time_delta": "10 minutes"}
elif id_triggered == "rt_rng_btn_5":
data = {"time_delta": "20 minutes"}
elif id_triggered == "rt_rng_btn_6":
data = {"time_delta": "1 hour"}
elif id_triggered == "rt_rng_btn_7":
data = {"time_delta": "all"}
else:
raise dash.exceptions.PreventUpdate
return data
Then you can convert the Input("store_rt_rangeselector", "data")
to a timedelta and use it to filter your charts (e.g. x_axis_start = x_axis_end - pd.Timedelta(time_delta)
or something like that.
Cheers,
Sean