I’m trying to create a dropdown menu that says ‘today’, ‘yesterday’, ‘last 7 days’ and ‘custom’. I want the calendar to automatically update when I choose an option in the dropdown menu. For ‘custom’ I want to pull the calendar so I can choose any dates I want. Here’s the sample code:
import dash import dash_core_components as dcc import dash_html_components as html from datetime import date as dt, timedelta import dash_bootstrap_components as dbc from dash.dependencies import Input, Output app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP]) app.layout = html.Div([ dcc.Dropdown( id = 'timeframe_dropdown', multi = False, options = [ {'label': 'Today', 'value': 'Today'}, {'label': 'Yesterday', 'value': 'Yesterday'}, {'label': 'Last 7 days', 'value': 'Last 7 days'}, {'label': 'Custom', 'value': 'None'} ], value='Today', clearable=False, ), dcc.DatePickerRange( id='datepicker', display_format='DD-MM-YYYY', first_day_of_week=1, min_date_allowed=dt(2019, 1, 1), max_date_allowed=dt(2021, 2, 28), ), ]) @app.callback( [Output('datepicker', 'start_date'), # This updates the field start_date in the DatePicker Output('datepicker', 'end_date')], # This updates the field end_date in the DatePicker [Input('timeframe_dropdown', 'value')], ) def updateDataPicker(dropdown_value): if dropdown_value == 'Today': return dt.today(), dt.today() elif dropdown_value == 'Yesterday': return dt.today() - timedelta(1), dt.today() - timedelta(1) elif dropdown_value == 'Last 7 days': return dt.today() - timedelta(6), dt.today() elif dropdown_value == 'Custom': return None else: return dt.today() - timedelta(6), dt.today() if __name__ == '__main__': app.run_server(host="0.0.0.0")
The dropdown and calendar show up on that code, however, they are not linked together. The dates in the calendar don’t change when I choose other options, it just stays in the date today by default.
Advertisement
Answer
You are almost there, just two small mistakes.
In your dropdown you are adding a new option to your dropdown {'label': 'Custom', 'value': 'None'}
. However you are setting its value to None
. The dropdown value are the ones we receive in the callback function as input [Input('timeframe_dropdown', 'value')]
. So in your if-statement you are checking elif dropdown_value == 'Custom':
. This will never be the case, as you set the Custom label to have value None
.
Another little mistake is that we are declaring two Output
values in the callback, both start_date
and end_date
, so we need to always return two values. elif dropdown_value == 'Custom': return None
should instead be elif dropdown_value == 'Custom': return None, None
.
Full code with fixes:
import dash import dash_core_components as dcc import dash_html_components as html from datetime import date as dt, timedelta import dash_bootstrap_components as dbc from dash.dependencies import Input, Output app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP]) app.layout = html.Div([ dcc.Dropdown( id = 'timeframe_dropdown', multi = False, options = [ {'label': 'Today', 'value': 'Today'}, {'label': 'Yesterday', 'value': 'Yesterday'}, {'label': 'Last 7 days', 'value': 'Last 7 days'}, {'label': 'Custom', 'value': 'Custom'} ], value='Today', clearable=False, ), dcc.DatePickerRange( id='datepicker', display_format='DD-MM-YYYY', first_day_of_week=1, min_date_allowed=dt(2019, 1, 1), max_date_allowed=dt(2021, 2, 28), ), ]) @app.callback( [Output('datepicker', 'start_date'), # This updates the field start_date in the DatePicker Output('datepicker', 'end_date')], # This updates the field end_date in the DatePicker [Input('timeframe_dropdown', 'value')], ) def updateDataPicker(dropdown_value): if dropdown_value == 'Today': return dt.today(), dt.today() elif dropdown_value == 'Yesterday': return dt.today() - timedelta(1), dt.today() - timedelta(1) elif dropdown_value == 'Last 7 days': return dt.today() - timedelta(6), dt.today() elif dropdown_value == 'Custom': return None, None else: return dt.today() - timedelta(6), dt.today() if __name__ == '__main__': app.run_server()