Skip to content
Advertisement

Dash Dynamic Dropdown with Custom Option

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()
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement