Hello all,
I am having an issue getting dynamic buttons (with unique index) to send to a pattern-matching call back. The purpose is to have a button for any possible result that comes up in a large database search, and when clicked the pattern-matching callback sends the data from a button with n_clicks=1 to update a separate table.
Currently this works fine when there is a single possible button to click, but if there are multiple results after the first button click, the pattern-match for ALL sends only the clicked button data for all of the buttons (duplicating it across). I have spent 2 days trying to understand how this is possible and am at a loss.
Here is the code I am using, and the frontend. So upon a search, dynamic buttons (in green) linked to the results should send their values.
app.layout = html.Div([
dbc.Container([
html.H5('Ticker Search'),
html.P('Search for new tickers to add to the watchlist'),
dbc.Input(
id="search_input",
type='text',
placeholder="input type"
),
html.Div(id="earnings-output")
], style={'align':'center'}),
dbc.Container([
html.H5('Current Watchlist'),
html.P(' ', id='watchlist-table'),
dcc.Interval(id='interval_component',
interval=3000,
n_intervals=0
),
]),
dbc.Container([
html.H5('Test'),
html.P(' ', id='test'),
html.P(' ', id='test2')
])
])
#Callback to auto-refresh the watchlist table every 3000 ms
@app.callback(Output('watchlist-table', 'children'),
[Input('interval_component', 'n_intervals')])
def watchlist_refresh(n_intervals):
results = sqlbackend.view_all('watchlist')
return dbc.Container([
dbc.Table(
# Header
[html.Tr([html.Th('Ticker:Region')]
)] +
# Body
[html.Tr([
html.Td(i[0], id='ticker-{}'.format(i[0])),
dbc.Button('Remove', color="danger", id={'type': 'remove', 'index': i[0]}, n_clicks=0)
]) for i in results], bordered=False
)
])
@app.callback(
Output('test', 'children'),
[Input({'type': 'add', 'index': ALL}, 'id'),
Input({'type': 'add', 'index': ALL}, 'n_clicks')],
# [State({'type': 'add', 'index': ALL}, 'n_clicks')]
)
def add_watchlist(values, clicks):
# print(values)
# print(clicks)
for i, j in enumerate(clicks):
print(values[i]['index'])
if j == 1:
print(values[i]['index'])
sqlbackend.insert_watchlist(values[i]['index'])
continue
return html.Div([
html.Div('{} = {}'.format(i + 1, value))
for (i, value) in enumerate(values)
])
@app.callback(
Output('test2', 'children'),
[Input({'type': 'remove', 'index': ALL}, 'id'),
Input({'type': 'remove', 'index': ALL}, 'n_clicks')],
# [State({'type': 'add', 'index': ALL}, 'n_clicks')]
)
#Callback to remove tickers from the watchlist
def remove_watchlist(values, clicks):
#print(values)
#print(clicks)
for i, j in enumerate(clicks):
if j == 1:
sqlbackend.delete_watchlist(values[i]['index'])
return html.Div([
html.Div('{} = {}'.format(i + 1, value))
for (i, value) in enumerate(values)
])
#Callback to search the earnings db by ticker and display
@app.callback(
Output("earnings-output", "children"),
[Input("search_input", "value")],
)
def earnings_search(search):
results = sqlbackend.view(search)[:5]
return dbc.Container([
dbc.Table(
# Header
[html.Tr([html.Th('Ticker'),
html.Th('Region'),
html.Th('Company Name'),
html.Th('Earnings Date')]
)] +
# Body
[html.Tr([
html.Td(i[0], id='ticker-{}'.format(i[0])),
html.Td(i[1]),
html.Td(i[2]),
html.Td(i[3]),
dbc.Button('Add', color="success", id={'type': 'add', 'index': '{}:{}'.format(i[0],i[1])}, n_clicks=0)
]) for i in results], bordered=False
)
])
if __name__ == "__main__":
app.run_server(debug=True)