Related
I want to trigger an event if the checkbox of a dash-table is clicked. When I start the webapp, I see below output
* Serving Flask app 'app'
* Debug mode: on
aaaa
[]
aaaa
[]
where "aaaa" indicating the callback is triggered. But when I click the checkbox after the initial load, nothing happens. I would expect that if I click the checkbox of a table, the callback-function dummy was triggered. Why is it not triggered?
import dash
import dash_bootstrap_components as dbc
from dash import html
from dash import dcc, dash_table
import plotly.express as px
from dash.dependencies import Input, Output
import pandas as pd
# data source: https://www.kaggle.com/chubak/iranian-students-from-1968-to-2017
# data owner: Chubak Bidpaa
df = pd.read_csv('https://raw.githubusercontent.com/Coding-with-Adam/Dash-by-Plotly/master/Bootstrap/Side-Bar/iranian_students.csv')
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
# styling the sidebar
SIDEBAR_STYLE = {
"position": "fixed",
"top": 0,
"left": 0,
"bottom": 0,
"width": "16rem",
"padding": "2rem 1rem",
"background-color": "#f8f9fa",
}
# padding for the page content
CONTENT_STYLE = {
"margin-left": "18rem",
"margin-right": "2rem",
"padding": "2rem 1rem",
}
sidebar = html.Div(
[
html.H2("", className="display-4"),
html.Hr(),
html.H2("Sidebar", className="display-4"),
html.Hr(),
html.P(
"Number of students per education level", className="lead"
),
dbc.Nav(
[
dbc.NavLink("Home", href="/", active="exact"),
dbc.NavLink("Page 1", href="/page-1", active="exact"),
dbc.NavLink("Page 2", href="/page-2", active="exact"),
],
vertical=True,
pills=True,
),
],
style=SIDEBAR_STYLE,
)
navbar = dbc.NavbarSimple(
children=[
dbc.NavItem(dbc.NavLink("Page 1", href="#")),
dbc.DropdownMenu(
children=[
dbc.DropdownMenuItem("More pages", header=True),
dbc.DropdownMenuItem("Page 2", href="#"),
dbc.DropdownMenuItem("Page 3", href="#"),
],
nav=True,
in_navbar=True,
label="More",
),
],
brand="NavbarSimple",
brand_href="#",
color="primary",
dark=True,
)
fig1 = px.bar(df, barmode='group', x='Years',
y=['Girls Kindergarten', 'Boys Kindergarten'])
fig1.update_layout(plot_bgcolor='rgb(10,10,10)')
children1 = [html.H1('Kindergarten in Iran',
style={'textAlign':'center'}),
dcc.Graph(id='bargraph',
figure=fig1),
dash_table.DataTable(
id='datatable-interactivity',
columns=[
{"name": i, "id": i, "deletable": True, "selectable": True} for i in df.columns
],
data=df.to_dict('records'),
editable=True,
filter_action="native",
sort_action="native",
sort_mode="multi",
column_selectable="single",
row_selectable="multi",
row_deletable=True,
selected_columns=[],
selected_rows=[],
page_action="native",
page_current= 0,
page_size= 10,
)]
content = html.Div(id="page-content", children=children1, style=CONTENT_STYLE)
app.layout = html.Div([
dcc.Location(id="url"),
sidebar,
navbar,
content
])
#fig1.update_layout(plot_bgcolor='rgb(10,10,10)')
"""
def update_styles(selected_columns):
return [{
'if': { 'column_id': i },
'background_color': '#D2F3FF'
} for i in selected_columns]
"""
#app.callback(
Output('datatable-interactivity', 'style_data_conditional'),
Input('datatable-interactivity', 'selected_columns')
)
def dummy(selected_columns):
print("aaaa")
print(selected_columns)
#app.callback(
Output("page-content", "children"),
[Input("url", "pathname")]
)
def render_page_content(pathname):
if pathname == "/":
return children1
elif pathname == "/page-1":
return children1
elif pathname == "/page-2":
return children1
# If the user tries to reach a different page, return a 404 message
return dbc.Jumbotron(
[
html.H1("404: Not found", className="text-danger"),
html.Hr(),
html.P(f"The pathname {pathname} was not recognised..."),
]
)
if __name__=='__main__':
app.run_server(debug=True)
The dummy function accepts a wrong input parameter. I have not worked with selected_columns, but selected_rows so far. A function input needed to be "chosen_rows" then for the selected_rows.
How do I please enable/disable auto-update (n_intervals) based on a boolean switch?
When the switch is turned off so that auto-update is not performed. And when it is on, so that the table is updated every 6 seconds?
Below I am posting the code that works for me with autoupdate (n_intervals).
import pandas as pd
import dash
from dash import html, Input, Output, callback, dash_table, dcc
import database
database = database.database()
dash.register_page(__name__)
layout = html.Div(
[
html.Div(id="table-container", children=[]),
dcc.Interval(id='interval-component', interval=6000, n_intervals=0),
]
)
#callback(Output('table-container', 'children'), [Input('interval-component', 'n_intervals')])
def update_table(n_intervals):
sql = pd.read_sql_query("SELECT * FROM PY_LOGGING ORDER BY LOG_TIME DESC FETCH FIRST 500 ROWS ONLY", database.connection())
df = pd.DataFrame(sql)
table = dash_table.DataTable(
id='table',
data = df.to_dict('records'),
columns = [{"name": i, "id": i} for i in df.columns],
fill_width=True,
page_size=20,
filter_action='native',
sort_action='native',
sort_mode='multi',
sort_as_null=['', 'No'],
style_table = {
"overflow": "hidden",
},
style_header = {
"text-transform": "uppercase",
"backgroundColor": "#333",
"color": "#FFFFFF",
"padding": "15px",
},
style_cell_conditional=[
{
'if': {'column_id': 'text_message'},
'textAlign': 'left'
}
],
style_data={
'whiteSpace': 'normal',
'height': 'auto',
'border-top': "1px solid #333",
'border-bottom': "1px solid #333",
'border-left': "0px solid #333",
'border-right': "0px solid #333",
},
style_data_conditional = [
{"if": {"column_id": "text_message"}, "width": "50%"},
{"if": {"column_id": "log_time"}, "width": "10%"},
{"if": {"column_id": "name_process"}, "width": "10%"},
{"if": {"column_id": "name_machine"}, "width": "10%"},
],
style_cell = {
# "padding": "15px",
"font-size": "0.8em",
}
)
return table
Thank you very much for your help.
John
I'm new to dash, I'm building an app in a django framework, part of the app is a dash table where the user will select cells, I want a callback that will format the current selected cell and those previously selected. So far I have tried two approaches with no luck, the first had some success, it formatted the active cell but didn't record the previously selected cells. The second approach has no success as the code doesn't seem to get read at all.
First approach:
dff=pd.Dataframe()
pre_sel=pd.Dataframe()
df4=[django_table] """df4 works fine and shows in below table so haven't included all code
here"""
app.layout= [ dash_table.DataTable(
id='table',
columns=[{"name": i, "id": i, 'type': 'numeric', 'format': Format(precision=4,
scheme=Scheme.fixed, trim=Trim.yes)} for i in df4],
data=df4.to_dict('records'),
style_table={'overflowX': 'scroll'}
)
)]
#app.callback(
Output('table', 'style_data_conditional'),
Input('table', 'active_cell')
)
def prev_sel(active_cell):
new_exc = pd.DataFrame(active_cell, index=[0]) if active_cell else None
pre_sel= dff.append(new_exc, ignore_index=True)
count = len(pre_sel)
exc = 0
style_data_conditional = []
while exc < count:
style_data_conditional = [
{
"if": {"column_id": pre_sel.iloc[exc, 2], "row_index": pre_sel.iloc[exc, 0]},
"backgroundColor": "rgba(150, 180, 225, 0.2)",
"border": "1px solid blue",
},
{
"if": {"column_id": "index"},
"backgroundColor": "rgba(116, 116, 117, .03)",
"border": "green",
"color": "black",
}
]
print(pre_sel)
print(pre_sel.iloc[exc, 0])
print(pre_sel.iloc[exc, 2]) """these were 3 print checks which were showing in console"""
exc += 1
return style_data_conditional
Second approach was to set up an empty dash table and write the data back:
clmnex =['row', 'column', 'column_id']
tablex = dash_table.DataTable(columns=[{'name': column, 'id': column} for column in clmnex],
data = [], id='tablex')
app.layout= [ dash_table.DataTable(
id='table',
columns=[{"name": i, "id": i, 'type': 'numeric', 'format': Format(precision=4,
scheme=Scheme.fixed, trim=Trim.yes)} for i in df4],
data=df4.to_dict('records'),
style_table={'overflowX': 'scroll'}
)
)]
#app.callback(
Output('table', 'style_data_conditional'),
Output('tablex', 'data'),
Input('table', 'active_cell'),
[Input('tablex', 'data')]
)
def prev_sel(active_cell,data):
new = pd.DataFrame(active_cell), """if active_cell else None"""
data += new.to_dict('records')
print('here')
count = len(data)
exc = 0
while exc < count:
style_data_conditional = [
{
"if": {"column_id": data.iloc[exc, 2], "row_index": data.iloc[exc, 0]},
"backgroundColor": "rgba(150, 180, 225, 0.2)",
"border": "1px solid blue",
},
{
"if": {"column_id": "index"},
"backgroundColor": "rgba(116, 116, 117, .03)",
"border": "green",
"color": "black",
}
]
exc += 1
return style_data_conditional, data
First approach had some success, it was just missing the recording previous selections, second never printed the 'here' statement, no idea why. Only need one of the approaches to work.
I've also noticed that I'm only able to pass one input to a function in callbacks, is this normal?
I have this dashboard am working on with a sample data as shown below
Time,Tp,Cl,pH,Redox,Leit,Trueb,Cl_2,Fm,Fm_2,EVENT
2016-02-15T11:54:00Z,4.4,0.14,8.38,755,232,0.009,0.11,1428,1020,FALSE
2016-02-15T11:55:00Z,4.4,0.14,8.38,755,232,0.009,0.111,1436,1018,FALSE
2016-02-15T11:56:00Z,4.4,0.14,8.38,755,232,0.014,0.113,1471,1019,TRUE
2016-02-15T11:57:00Z,4.4,0.14,8.37,755,232,0.015,0.111,1457,1015,FALSE
2016-02-15T11:58:00Z,4.4,0.14,8.38,755,232,0.013,0.111,1476,1019,FALSE
2016-02-15T11:59:00Z,4.4,0.14,8.36,755,232,0.013,0.114,1416,1015,TRUE
2016-02-15T12:00:00Z,4.4,0.14,8.36,755,235,0.012,0.111,1452,1017,FALSE
I filter the data and display it as a plot using 3 dropdown. Basically i want to plot columns(Tp to Fm_2) (first dropdown)within a date-range(second dropdown),and also the option of whether the event is true ?false(third dropdown). Below is the code to do that, first and third option is working fine, however the second option isn't. Any help to why this isn't working.
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.title = "Sensor Analytics: Understanding Your Metrics!"
app.layout = html.Div(
children=[
html.Div(
children=[
html.P(children="", className="header-emoji"),
html.H1(
children="Sensor Analytics", className="header-title"
),
html.P(
children="Visualization analysis of sensor readings "
,
className="header-description",
),
],
className="header",
),
html.Div(
children=[
html.Div(
children=[
html.Div(children="Metrics", className="menu-title"),
dcc.Dropdown(
id="metrics-filter",
options=[
{"label": col, "value": col}
for col in data.columns
],
value="Tp",
clearable=False,
className="dropdown",
),
]
),
html.Div(
children=[
html.Div(children="Event", className="menu-title"),
dcc.Dropdown(
id="event-filter",
options=[
{"label": 'False', "value":'False'},
{"label": 'True', "value":'True'}
],
value="False",
clearable=False,
searchable=False,
className="dropdown",
),
],
),
html.Div(
children=[
html.Div(
children="Date Range", className="menu-title"
),
dcc.DatePickerRange(
id="date-range",
min_date_allowed=data.Time.min().date(),
max_date_allowed=data.Time.max().date(),
start_date=data.Time.min().date(),
end_date=data.Time.max().date(),
),
]
),
],
className="menu",
),
html.Div(
children=[
html.Div(
children=dcc.Graph(
id="series1",
config={"displayModeBar": False},
),
className="card",
),
],
className="wrapper",
),
]
)
#app.callback(
Output("series1", "figure"),
[
Input("metrics-filter", "value"),
Input("event-filter", "value"),
Input("date-range", "start_date"),
Input("date-range", "end_date"),
],
)
def update_charts(metrics,event,start_date, end_date):
df = data
mask =((df.Time >= start_date) & (df.Time <= end_date))
df_selected = df.loc[mask,:]
if (event == 'True') :
df_selected = df[df['EVENT']==True]
else:
df_selected = df[df['EVENT']==False]
chart_figure = {
"data": [
{
"x": df_selected["Time"],
"y": df_selected[metrics],
"type": "lines",
"hovertemplate": "%{y:.2f}<extra></extra>",
},
],
"layout": {
"title": {
"text": "Sensor readings",
"x": 0.05,
"xanchor": "left",
},
"xaxis": {"fixedrange": True},
"yaxis": {"tickprefix": "", "fixedrange": True},
"colorway": ["#17B897"],
},
}
return chart_figure
if __name__ == "__main__":
app.run_server(debug=True)
I would like to style row based on a value of a column, I currently have this code:
import dash
import dash_table
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/solar.csv')
app = dash.Dash(__name__)
print([{"name": i, "id": i} for i in df.columns])
app.layout = dash_table.DataTable(
id='table',
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict("rows"),
style_data_conditional=[
{
'if': {
'column_id': 'Number of Solar Plants',
'filter': '"Number of Solar Plants" > num(100)'
},
'backgroundColor': '#3D9970',
'color': 'white',
}
],
)
if __name__ == '__main__':
app.run_server(debug=True)
Which produces the following result:
But what I really want is for the rows (tr 1 and 8 in this case) to be styled with a green background, not just the cells.
What can I do to achieve this?
to fix your issue you just have to remove the column_id parameter in your style_data_conditional. So all the row will be colored in green.
You should do this:
style_data_conditional=[
{
'if': {
'filter': '"Number of Solar Plants" > num(100)'
},
'backgroundColor': '#3D9970',
'color': 'white',
}
]