dash
dash copied to clipboard
append not working as expected with partial property updates
Issue reported by community on the forum. @T4rk1n and I took a deeper look into it but we couldn't pinpoint the location of the bug exactly. There may be a bug in the graph component or Plotly.js.
The Problem
The append Patch method does not work, although it's nearly an exact replica of this example code in the docs.
It appears to create a new line on first call, then it appends to the new line for the subsequent call. According to @T4rk1n , it's actually not a new line but it draws the first appended item from the first point on the line.
from dash import Dash, html, dcc, Input, Output, Patch, callback, State
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import datetime
import random
app = Dash(__name__)
# Create a subplot with 2 rows and 1 column
fig = make_subplots(rows=2, cols=1, shared_xaxes=True)
# Initialize the figure with some default data
initial_x = [datetime.datetime.now() - datetime.timedelta(minutes=i) for i in range(5)]
initial_y1 = [random.randrange(1, 30, 1) for _ in range(5)]
initial_y2 = [random.randrange(1, 30, 1) for _ in range(5)]
initial_y3 = [random.randrange(1, 30, 1) for _ in range(5)]
initial_y4 = [random.randrange(1, 30, 1) for _ in range(5)]
fig.add_trace(go.Scatter(x=initial_x, y=initial_y1, mode='lines+markers', name='Trace 1.1'), row=1, col=1)
fig.add_trace(go.Scatter(x=initial_x, y=initial_y2, mode='lines+markers', name='Trace 1.2'), row=1, col=1)
fig.add_trace(go.Scatter(x=initial_x, y=initial_y3, mode='lines+markers', name='Trace 2.1'), row=2, col=1)
fig.add_trace(go.Scatter(x=initial_x, y=initial_y4, mode='lines+markers', name='Trace 2.2'), row=2, col=1)
# print(fig)
app.layout = html.Div(
[
html.Button("Append", id="append-new-val"),
dcc.Graph(figure=fig, id="append-example-graph"),
]
)
@callback(
Output("append-example-graph", "figure"),
Input("append-new-val", "n_clicks"),
State("append-example-graph", "figure"),
prevent_initial_call=True,
)
def add_data_to_fig(n_clicks, fig1):
current_time = datetime.datetime.now()
# Generate random values for each trace
random_values = [random.randrange(1, 30, 1) for _ in range(4)]
patched_figure = Patch()
# Update first subplot, first trace
patched_figure["data"][0]["x"].append(current_time)
patched_figure["data"][0]["y"].append(random_values[0])
# # Update first subplot, second trace
# patched_figure["data"][1]["x"].append(current_time)
# patched_figure["data"][1]["y"].append(random_values[1])
#
# # Update second subplot, first trace
# patched_figure["data"][2]["x"].append(current_time)
# patched_figure["data"][2]["y"].append(random_values[2])
#
# # Update second subplot, second trace
# patched_figure["data"][3]["x"].append(current_time)
# patched_figure["data"][3]["y"].append(random_values[3])
# # print('')
# # print(fig1)
return patched_figure
if __name__ == "__main__":
app.run(debug=True)