Callbacks on drag and drop button

Hello I have an app that interact with a ML model and returns a score when I input values through sliders but I also have a drag and drop button where I drop a dataframe and interact with my model then return a prediction. The probleme is after being used, the drag and drop button freeze my other page widgets. How can I solve this to reset the drag and drop state ?


@app.callback(
    Output('output-data-upload', 'children'),
    Output('model-output', 'children'),
    Output('reset-store', 'data'),
    Input('upload-data', 'contents'),
    State('upload-data', 'filename'),
    Input('age-slider', 'value'),
    Input('for-slider', 'value'),
    Input('rek-slider', 'value'),
    Input('hmg-slider', 'value'),
    Input('gonal-slider', 'value'),
    Input('ov-slider', 'value'),
    Input('policy-radio', 'value'),
    Input('registered-radio', 'value'),
    Input('apem-radio', 'value'),
    Input('reset_button', 'n_clicks'),
    State('reset-store', 'data'),
    )
def update_output(list_of_contents, list_of_names, value_age, value_for, value_rek, value_hmg, value_gonal, value_ov, value_policy, value_registered, value_apem, n_clicks, reset_data):
    ctx = dash.callback_context

    if not ctx.triggered:
        return None, None, reset_data

    triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]

    if triggered_id == 'reset_button':
        return None, None, {'reset': True}

    if reset_data['reset']:
        return None, None, {'reset': False}

    if list_of_contents is not None:
        for contents, name in zip(list_of_contents, list_of_names):
            df = parse_contents(contents, name)
    else:
        input_dict = {
            'age': value_age,
            'for_user': value_for,
            'rek_user': value_rek,
            'hmg_user': value_hmg,
            'gonal_user': value_gonal,
            'ov_user': value_ov,
            'policy': value_policy,
            'registered_not_joined_3months': value_registered,
            'apem_status_opened_and_clicked': value_apem
        }
        columns_order = ['policy', 'hmg_user', 'registered_not_joined_3months', 'age', 'gonal_user', 'ov_user', 'apem_status_opened_and_clicked', 'rek_user', 'for_user']
        df = pd.DataFrame([input_dict], columns=columns_order)
    prediction_output = predict_proba_return_html(pipeline, df)
    return None, prediction_output, reset_data

Hey @jedg welcome to the forms. Maybe a bit late, but with the given information its hard to tell. Could you provide a reproducible example?

Hello Aimped,

First time doing this so please forgive me if my message is unclear!

That is my simplified code.

The problem is that after drag and dropping an object, it takes over the slider’s output and the slider is not usable anymore.

Thank you for your time!

import dash
from dash import Dash, dcc, html, Input, Output, State
import pandas as pd
import base64
import io

data = {
    'age': [25, 30, 35, 40, 45, 50, 55, 60, 65, 70]
}
df = pd.DataFrame(data)

app = Dash(__name__)

app.layout = html.Div([
    html.Label("Age"),
    dcc.Slider(
        id='age-slider',
        min=df['age'].min(),
        max=df['age'].max(),
        value=df['age'].mean(),
        marks={i: str(i) for i in df['age']}
    ),
    html.Div(id='slider-output'),
    html.Div([
        dcc.Upload(
            id='upload-data',
            children=html.Div([
                'Drag and Drop or ',
                html.A('Select Files')
            ]),
            multiple=True
        ),
        html.Div(id='output-data-upload'),
        html.Button('Reset', id='reset_button', style={'fontSize': '20px', 'padding': '10px 20px', 'margin': '20px auto', 'display': 'block'}),
        dcc.Store(id='reset-store', data={'reset': False})
    ])
])

@app.callback(
    Output('output-data-upload', 'children'),
    Output('slider-output', 'children'),
    Output('reset-store', 'data'),
    Input('upload-data', 'contents'),
    State('upload-data', 'filename'),
    Input('age-slider', 'value'),
    Input('reset_button', 'n_clicks'),
    State('reset-store', 'data')
)
def update_output(list_of_contents, list_of_names, value_age, n_clicks, reset_data):
    ctx = dash.callback_context

    if not ctx.triggered:
        return None, None, reset_data

    triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]

    if triggered_id == 'reset_button':
        return None, None, {'reset': True}

    if reset_data['reset']:
        return None, None, {'reset': False}

    if list_of_contents is not None:
        for contents, name in zip(list_of_contents, list_of_names):
            df = parse_contents(contents, name)
    else:
        df = pd.DataFrame([{'age': value_age}])

    slider_output = f'Selected Age: {value_age}'
    return None, slider_output, reset_data

def parse_contents(contents, filename):
    content_type, content_string = contents.split(',')
    decoded = base64.b64decode(content_string)
    df = pd.read_csv(io.StringIO(decoded.decode('utf-8')))

I actually do not understand what you are trying to do. What is the dcc.Store() for?

BTW, you can import ctx and do this:

@app.callback(
    Output('output-data-upload', 'children'),
    Output('slider-output', 'children'),
    Output('reset-store', 'data'),
    Input('upload-data', 'contents'),
    State('upload-data', 'filename'),
    Input('age-slider', 'value'),
    Input('reset_button', 'n_clicks'),
    State('reset-store', 'data'),
    prevent_initial_call=True
)
def update_output(list_of_contents, list_of_names, value_age, n_clicks, reset_data):
    triggered_id = ctx.triggered_id    

    if triggered_id == 'reset_button':
        return None, None, {'reset': True}

    if reset_data['reset']:
        return None, None, {'reset': False}

    if list_of_contents is not None:
        for contents, name in zip(list_of_contents, list_of_names):
            df = parse_contents(contents, name)
    else:
        df = pd.DataFrame([{'age': value_age}])

    slider_output = f'Selected Age: {value_age}'
    return None, slider_output, reset_data

I am trying to reset the state of the drag and drop file after I used it. Indeed when I use my slider at the beginning it works and the reset button also. But when I try to load data with drag and drop, then I can’t use my slider anymore. I want to reset the state of the drag and drop to be able to use again my slider. And that in the same session.

Thank you for your help !

Much much appreciated !