Hi,
Is it possible to know which component was the one that triggered some particular callback?
Thanks,
Yossi
Hi,
Is it possible to know which component was the one that triggered some particular callback?
Thanks,
Yossi
It isn’t right now, but this PR https://github.com/plotly/dash/pull/140 is a proposition to make this possible.
Fore more, see this community thread: Input two or more button - How to tell which button is pressed?
I would like something similar, and what may work is to have hidden elements which record a timestamp of the last modification, and them from these timestamps, pick the control which was touched last. Potential problems:
There might be other problems I haven’t thought of. Here’s an example:
import time
import json
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
from dash import Dash
def update_timestamp(input):
return time.time()
def choose_latest(*timestamps_and_states):
assert len(timestamps_and_states) % 2 == 0
midpoint = len(timestamps_and_states) // 2
timestamps = timestamps_and_states[:midpoint]
states = timestamps_and_states[midpoint:]
most_recent = states[timestamps.index(max(timestamps))]
return json.dumps(most_recent)
app = Dash()
app.layout = html.Div([
dcc.Input(id='input-a', type="text"),
dcc.Input(id='input-b', type="text"),
dcc.Input(id='input-c', type="text"),
html.Div(
[
'Timestamps:', html.Br(),
'A: ', html.Span(id='input-a-timestamp'), html.Br(),
'B: ', html.Span(id='input-b-timestamp'), html.Br(),
'C: ', html.Span(id='input-c-timestamp'), html.Br(),
],
style={'display': 'block'} # Switch this on or off for debugging.
),
html.Span(['and the latest value is: ']),
html.Span(id='latest-value')
])
app.callback(
Output('input-a-timestamp', 'children'), [Input('input-a', 'value')]
)(update_timestamp)
app.callback(
Output('input-b-timestamp', 'children'), [Input('input-b', 'value')]
)(update_timestamp)
app.callback(
Output('input-c-timestamp', 'children'), [Input('input-c', 'value')]
)(update_timestamp)
app.callback(
Output('latest-value', 'children'),
[Input('input-a-timestamp', 'children'),
Input('input-b-timestamp', 'children'),
Input('input-c-timestamp', 'children')],
[State('input-a', 'value'),
State('input-b', 'value'),
State('input-c', 'value')]
)(choose_latest)
app.run_server()
Thanks Mccalluc, Great idea.
I implemented your method and I thought id show a simplified example of it.
Please note all the potential problems Mccalluc pointed out.
You can add as many html/dcc components as you want, following the same pattern with the timekeeper divs.
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import time
app = dash.Dash()
app.layout = html.Div([
# hidden div for holding timestamp of any DCC or html component
html.Div(id='dcc-timekeeper', children='0', style={'display': 'none'}),
# Any DCC or html item you want to use for ordered trigger
dcc.Dropdown(id='dcc-item',
options=[
{'label': 'Chriddyp', 'value': 'Hr'},
{'label': 'Please notice me', 'value': 'Day'}
],
value='Hr'
),
# 3 buttons to compare to for ease (these can use n_clicks_timestamp like in previous examples)
html.Button(id='btn1',
children='btn1',
n_clicks_timestamp='0'),
html.Button(id='btn2',
children='btn2',
n_clicks_timestamp='0'),
html.Button(id='btn3',
children='btn3',
n_clicks_timestamp='0'),
html.Div(id='results')
])
# use your DCC or html item to trigger a callback to update the dcc-timekeeper div
@app.callback(Output('dcc-timekeeper', 'children'),
[Input('dcc-item', 'value')])
def update_timebase_nclick(value):
return '{}'.format(int(time.time() * 1000))
# use multiple inputs and figure out which one was the trigger as such:
@app.callback(Output('results', 'children'),
[Input('btn1', 'n_clicks_timestamp'),
Input('btn2', 'n_clicks_timestamp'),
Input('btn3', 'n_clicks_timestamp'),
Input('dcc-timekeeper', 'children'),
Input('dcc-item', 'value')])
def slider_buttons(btn1, btn2, btn3, btn4, dccvalue):
if int(btn1) > int(btn2) and int(btn1) > int(btn3) and int(btn1) > int(btn4):
val = 'btn1'
elif int(btn2) > int(btn1) and int(btn2) > int(btn3) and int(btn2) > int(btn4):
val = 'btn2'
elif int(btn3) > int(btn1) and int(btn3) > int(btn2) and int(btn3) > int(btn4):
val = 'btn3'
elif int(btn4) > int(btn1) and int(btn4) > int(btn2) and int(btn4) > int(btn3):
val = 'Dcc item'
return '{}'.format(val)
if __name__ == '__main__':
app.run_server(debug=True)