Good day all.
I would like to bind the callback function dynamically to dynamically generated graphs(from a python Dictionary(from JSON from MQTT))
I managed to generate the UI(Visuals) but was unable to bind it with the right callbacks. UI generation(a MWE):
def generate_sensing_ui(sensing_json):
graphing_list = []
for thingName in list(sensing_json.keys()):
graphID = "graph-"+str(thingName)
graphing_list.append(html.Div(
children=[
dcc.Graph(id=graphID),
]))
return graphing_list # returns to a html.Div
All good at this point. Follow is the codeblock for Callbacks Binding (which will be evoked at start of script):
def function_123(sensing_dict):
for sensor in list(sensing_dict.keys()):
graphID = "graph-"+str(sensor)
@app.callback(
Output(graphID, 'figure'),
Input('update', 'n_intervals')
)
def sensing_ui_callbacks_attaching(n_intervals):
thingName = graphID[6:]
if dictionary_with_sensor:
graphDatastream = dictionary_with_sensor[thingName]["Datastream"]
x_values = []
y_values = []
for j in graphDatastream:
x_values.append(list(j.keys())[0])
y_values.append(list(j.values())[0])
figure = go.Figure(
data=[go.Scatter(x=x_values, y=y_values)],
)
figure.update_layout(
title=thingName,
xaxis_title= list((dictionary_with_sensor[thingName]["Format"]).keys())[0],
yaxis_title= list((dictionary_with_sensor[thingName]["Format"]).values())[0],
template="plotly_dark",
)
return figure
else:
pass
Problem: It will generate x number of graphs but all have the same content, which is the last entry of the Dictionary. The for loop works(tested with printing inside the block.
I think I pinpointed the problem. Potential cause: This function binds the UI and the callback but it does not “tell” or “set” the current variable into the respective functions. Hence the variable, “graphID” will take the last value of the list and generate the graph with the last value of the list as the key(in the dictionary).
So I am thinking of the following potential solution:
- Set/Pass in a variable into the “function_123” during the for loop and make sure it doesn’t get updated.
- Takes in 2 inputs, namely “n_intervals” and the id of the graph(in HTML), then processes the ID into a dictionary key and plots the graphs. As every n_intervals it will fire the function, so having the ID as a string along with the n_intervals, might work.
However, I tried(I really did), not sure how to get around this.
Well, thanks for your time reading up to this point, sorry for my bad command of language. Let me know if word it wrongly or so.
Do share if you have any ideas. Much appreciated.
Cheers,
Mocha.
P.S. I use the following as reference/inspiration: Dynamically declaration of dash callback