Hi Everybody,
Today @AnnMarieW and I performed an option to have a kind of Button inside a Dash data Table.
Let me explain the trick:
- Use active_cell property of the table as Input of a callback.
- The active_cell property has (at least) 3 elements of the active cell, those are row, column, and column_id.
- That means if a user selects the second element of the first column the active_cell will give us the following information: {‘row’: 1, ‘column’: 0, ‘column_id’: ‘first_column_name’}
- Then using the derived_viewport_data property we can find and select the element inside the active cell selected by the user.
- And with that element we can perform any action releated with that element as when the user clicks a specific Button.
Let me show you two different examples:
- In the first one only when the user select an element of the first column the callback search for that specific element in an other link. That means if the active cell is not in the first column the callback will do nothing.
- In the second, the user can select any cell of the table, and the output will show the element of the selected cell, no matters to wich column belongs that cell.
First example: It shows a table from yahoo finance data from today’s stock losers and if the user select a Symbol, the callback will call an app to analize that Company.
import dash
from dash.dependencies import Input, Output, State
import dash_table
import dash_html_components as html
import pandas as pd
import dash_core_components as dcc
app = dash.Dash(__name__)
# get the table of todays losers from Yahoo finance
urlyahoo = 'https://finance.yahoo.com/losers'
tables = pd.read_html(urlyahoo)
losers = pd.DataFrame(tables[0])
losers.drop(['Volume', 'Avg Vol (3 month)', 'PE Ratio (TTM)', '52 Week Range'], axis='columns', inplace=True)
app.layout = html.Div(
[
html.H2("This table has the Yahoo Today's Losers"),
html.H2("Select the Symbol you want to analyze:"),
dash_table.DataTable(
id="table",
fixed_rows={'headers': True},
columns=[{"name": i, "id": i} for i in losers.columns],
data=losers.to_dict("records"),
is_focused=True,
style_data_conditional=[
{'if': {'column_id': 'Symbol'}, 'backgroundColor': 'green', 'text_align':'center','color': 'white'},
{'if': {'column_id': '% Change'}, 'backgroundColor': 'yellow', 'color': 'red', 'font-weight': 'bold'},
],
),
dcc.Location(id='location'),
]
)
@app.callback(
Output("location", "href"),
Input("table", "active_cell"),
State("table", "derived_viewport_data"),
)
def cell_clicked(active_cell, data):
if active_cell:
row = active_cell["row"]
col = active_cell["column_id"]
if col == "Symbol": # or whatever column you want
selected = data[row][col]
return f"https://companyanalysis.herokuapp.com/{selected}"
else:
return dash.no_update
if __name__ == "__main__":
app.run_server(debug=True)
The second will get any element selected by the user:
import dash
from dash.dependencies import Input, Output, State
import dash_table
import dash_html_components as html
import pandas as pd
app = dash.Dash(__name__)
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/solar.csv")
app.layout = html.Div(
[
dash_table.DataTable(
id="table",
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict("records"),
is_focused=True,
),
html.Div(id="output"),
]
)
@app.callback(
Output("output", "children"),
Input("table", "active_cell"),
State("table", "derived_viewport_data"),
)
def cell_clicked(cell, data):
if cell:
selected = data[cell["row"]][cell["column_id"]]
return f"You have selected {selected}"
else:
return dash.no_update
if __name__ == "__main__":
app.run_server(debug=True)
And also you can style the elements before and after the user select the cell to gave the impresion that the user are clicking a button or a Link.
This is just expamples to show how the callbacks takes the element selected by the user, in the first example it could be possible to directly use markdown with a url link.