Hello, guys so I’ve some problems where I want to make, Inspired by this answer callback - Plotly-Dash: How to update DatePickerRange dynamically from dropdown - Stack Overflow, I try to make this version on my own but it’s not complete yet, maybe there’re many mistakes also.
Purposes :
- Generally, I want to make a dropdown list contains ( Today, Yesterday, Last 7 days, and Modified Date ) → change the date picker’s value & save it into a session.
- If the date picker’s value is changed then → Update the dropdown list and save it into session
- Every page load, fetch the session, and update the dropdown list and the date pickers.
a. This is my layout.
app.layout = html.Div([dcc.Dropdown(
id = 'timeframe_dropdown',
multi = False,
options = [
{'label':'Modified Range','value':'date_picker'},
{'label': 'Today', 'value': 'Today'},
{'label': 'Yesterday', 'value': 'Yesterday'},
{'label': 'Last 7 days', 'value': 'Last 7 days'}
],
value='date_picker',
clearable=False,
),
dcc.DatePickerRange(
id='my-date-picker-range'
),
dcc.Store(id='session',storage_type='session')])
b. This is my callback for datepicker
@app.callback(
[Output('my-date-picker-range', 'start_date'),Output('my-date-picker-range', 'end_date')]
,[Input('session','modified_timestamp')],State('session','data'))
def updateDataPicker(ts,data):
ctx = dash.callback_context
if ctx.triggered[0]['prop_id'] != '.':
raise PreventUpdate
if data is None:
return date.today() - timedelta(6), date.today()
if (data.get('set_dp') is None):
data = True
data = dict({'st':datetime.now().date(),'et':datetime.now().date(),'set_dp':'date_picker'})
if (data.get('set_dp') == 'date_picker'):
# data = data or dict({'st':datetime.now().date(),'et':datetime.now().date(),'set_dp':'date_picker'})
return data.get('st'),data.get('et')
if data.get('set_dp') == 'Today':
return date.today(), date.today()
elif data.get('set_dp') == 'Yesterday':
return date.today() - timedelta(1), date.today() - timedelta(1)
else:
return date.today() - timedelta(6), date.today()
c. This is callback for saving unto session
@app.callback( Output (‘session’,‘data’), [Input(‘my-date-picker-range’,‘start_date’),Input(‘my-date-picker-range’,‘end_date’),Input(‘timeframe_dropdown’,‘value’)] , State(‘session’,‘data’))
def on_data(st,et,val,data):
if st is None or et is None:
raise PreventUpdate
data = {'st':datetime.now().date(),'et':datetime.now().date()}
data['st'] = st
data['et'] = et or datetime.now().date()
data['set_dp'] = val
return data
d. This is callback for dropdown list
@app.callback(
Output('timeframe_dropdown','value')
,Input ('session','modified_timestamp'),State('session','data'))
def onsite(ts,data):
if ts is None:
return 'Today'
ctx = dash.callback_context
if ctx.inputs['my-date-picker-range.start_date'] is not None and ctx.inputs['my-date-picker-range.end_date'] is not None:
sts = datetime.strptime(ctx.inputs['my-date-picker-range.start_date'], '%Y-%m-%d')
ets = datetime.strptime(ctx.inputs['my-date-picker-range.end_date'], '%Y-%m-%d')
delta = ets-sts
if delta.days == 0 :
return 'Today'
elif delta.days == 1:
return 'Yesterday'
elif delta.days == 7-8:
return 'Last 7 days'
else:
return 'date_picker'
else:
return 'date_picker'
The question is :
- Can I run the callback only for page load? Afaik, there’s no feature like this, or maybe there’s an algorithm that more or less the same with this feature?
- This duplicated output callback makes plotly isn’t flexible at all, so if my algorithm was right, I want to make the output specifically for the first page-load, and the other output with the same id is for user interaction.
- I know my code isn’t perfect at all, so can u guys help me try to rebuild the code to achieve my goals?