Callback is delayed

Hi,

in my app I would like to show the results of the html.Div 'Zement_gesamt_gwp' to the user as soon as he puts the amount into the “Menge [kg]” input box (see relevant code excerpt below).
Howerver, in my current code, the callback is not triggered before the user selects something from the “Transport” dropdown and I don’t know why the code “delays” the callback.

How can I modify the code to have the callback triggered immediately when the user adds the amount into the “Menge [kg]” input box?

Thank you!


    dbc.Col([

                    html.Div([html.H5('Zement', style={"height": "30px", 'margin-top': '12px', 'margin-bottom':'12px', 'justyfy-content': 'center'}),
                    dcc.Dropdown(
                        df["Werk"].unique(),
                        placeholder='Werk',
                        id='Werksauswahl',
                        style={'text-align':'left', "width": "230px", 'margin-right':'25px'}),

                    dcc.Dropdown(
                        df["Zement"],
                        placeholder='Zementtyp',
                        id='Zementauswahl',
                        style={'text-align':'left', "width": "230px", 'margin-right':'25px'}),
                    
                    ]),

                    html.Div([html.H5('Menge [kg]', style={"height": "30px", 'margin-top': '12px', 'margin-bottom':'12px'}),
                    dcc.Input(
                        id='Zementmenge_input',
                        type='number',
                        value=0,
                        placeholder='Menge [kg]',
                        style={'height':'35px', 'margin-right':'25px'})]),


                    html.Div([html.H5('Transport', style={"height": "30px", 'margin-top': '12px', 'margin-bottom':'12px', 'justyfy-content': 'center'}),
                    dcc.Dropdown(
                        df1['Prozess'].loc[10:12],
                        placeholder='Transportmittel',
                        id='Transportauswahl1',
                        style={'text-align':'left', "width": "230px", 'margin-right':'25px'})]),


                    html.Div([html.H5('Entfernung [km]', style={"height": "30px", 'margin-top': '12px', 'margin-bottom':'12px'}),
                    dcc.Input(
                        id='Transport_input1',
                        type='number',
                        value=0,
                        style={'height':'35px'}),
                        html.Div(id='Transport_zement_gwp', style={'color':'blue', 'font-size': '12px'})
                    ]),

                ], style={'display':'flex', 'margin-right':'25px'}),

        
            html.Div(id='Zement_gesamt_gwp', style={'color':'red', 'font-size': '12px'}),

@app.callback(
    [dash.dependencies.Output('Zement_gesamt_gwp', 'children'),
    dash.dependencies.Output('Transport_zement_gwp', 'children'),
    dash.dependencies.Output('Transport_zement_gwp2', 'data'),
    dash.dependencies.Output('Total_zement_gwp', 'data')],
    [dash.dependencies.Input('Werksauswahl', 'value'),
    dash.dependencies.Input('Zementauswahl', 'value'),
    dash.dependencies.Input('Zementmenge_input', 'value'),
    dash.dependencies.Input('Transportauswahl1', 'value'),
    dash.dependencies.Input('Transport_input1', 'value')],

    
    prevent_initial_callback=True
    
    )
def get_gwp_value (selected_werk, selected_cement, selected_amount, selected_transport, selected_distance):

    if selected_amount is None or selected_transport is None or selected_distance is None:
        raise dash.exceptions.PreventUpdate

    else:
        
        if selected_amount is not None and selected_distance is not None:
            gwp_z = df['GWP_netto'][(df['Werk']==selected_werk) & (df['Zement']==selected_cement)]
            zement_gwp = gwp_z*selected_amount
            zement_gwp = round(zement_gwp, 2)
            gwp_t = df1['GWP'][(df1['Prozess']==selected_transport)]
            transport_gwp = gwp_t*selected_distance*(selected_amount / 1000)
            transport_z_gwp = round(transport_gwp, 2)
        return zement_gwp.astype(str) + str(' kg CO2/e'), transport_z_gwp.astype(str) + str(' kg CO2/e'), transport_z_gwp, zement_gwp

Hi @slyfox,

The callback isn’t returning anything because you raise PreventUpdate if there is no value for selected_transport.

if selected_amount is None or selected_transport is None or selected_distance is None:
        raise dash.exceptions.PreventUpdate

You can fix this by making the conditional statements as specific as possible, and ensuring each conditional encapsulates what is encompassed below it. Here’s an example of splitting your single conditional into multiple conditionals for tighter control.

@app.callback(
    [dash.dependencies.Output('Transport_zement_gwp', 'children'),
     dash.dependencies.Output('Transport_zement_gwp2', 'data'),
     dash.dependencies.Output('Zement_gesamt_gwp', 'children'),
     dash.dependencies.Output('Total_zement_gwp', 'data')],
    [dash.dependencies.Input('Werksauswahl', 'value'),
     dash.dependencies.Input('Zementauswahl', 'value'),
     dash.dependencies.Input('Zementmenge_input', 'value'),
     dash.dependencies.Input('Transportauswahl1', 'value'),
     dash.dependencies.Input('Transport_input1', 'value')],
    prevent_initial_callback=True

)
def get_gwp_value(selected_werk, selected_cement, selected_amount, selected_transport, selected_distance):
    # required for both transport and total
    if not selected_amount:
        raise dash.exceptions.PreventUpdate

    # check for zement items
    if selected_werk and selected_cement:
        gwp_z = df['GWP_netto'][(df['Werk'] == selected_werk) & (df['Zement'] == selected_cement)]
        zement_gwp = gwp_z * selected_amount
        zement_gwp = round(zement_gwp, 2)
        zement_children, zement_data = zement_gwp.astype(str), zement_gwp
    else:
        zement_children, zement_data = None, None

    # check for transport items
    if selected_transport and selected_distance and selected_amount:
        gwp_t = df1['GWP'][(df1['Prozess'] == selected_transport)]
        transport_gwp = gwp_t * selected_distance * (selected_amount / 1000)
        transport_z_gwp = round(transport_gwp, 2)
        transport_gwp_children, transport_gwp_data = transport_z_gwp.astype(str) + str(' kg CO2/e'), transport_z_gwp
    else:
        transport_gwp_children, transport_gwp_data = None, None

    return transport_gwp_children, transport_gwp_data, zement_children, zement_data
1 Like

Thank you @3d65 for your help! That is a great solution, much appreciated.

1 Like