Black Lives Matter. Please consider donating to Black Girls Code today.
Dash HoloViews is now available! Check out the docs.

Force Callback order

I have a tab and a RadioItem that only fill when data is uploaded.

However the tab contains the ID for the RadioItem. However when data is uploaded the RadioItem does not populate the first time. It does populate the second time data is uploaded. I think its because when the callbacks are launched the RadioItem tries to work first, except it doesn’t exist at that point.

In What is the execution order of callbacks? the order is said to either be determined automatically or at random.

I was wondering is there a way to impose an order for “seemingly” unrelated callbacks (Since the RadioItem fails to populate every time so there does seem to be some order).

Huge appreciation for any help

Could you create a really small, simple reproducable example?

With pleasure.

I have tired to keep it short however since I need the callbacks its still a bit long:

import dash_html_components as html
import dash_core_components as dcc
import dash
from dash.dependencies import Input, Output, State

import pandas as pd

import json
import base64
import io

app = dash.Dash()

New_Input = [
        html.Div(html.H5("Column Data you want to Display")),
        html.Div(
            children =[
                dcc.RadioItems(
                    id = "Column_Names1",
                    value="",
                ),
            ],
        ),
    ]

app.config["suppress_callback_exceptions"] = True

app.layout = html.Div(
    children = [
        html.Div(id="DataFrame"),
        html.Div([
            dcc.Upload(
                id="upload-data",
                children=html.Div([
                    "Drag and Drop or ",
                    html.A("Select Files")
                ]),
                multiple=False),
        ]),
        html.Div(id = "New_Input")
    ]
)

def parse_contents(contents, filename):
    content_type, content_string = contents.split(",")
    decoded = base64.b64decode(content_string)
    try:
        if "csv" in filename:
            # Assume that the user uploaded a CSV file
            df = pd.read_csv(
                io.StringIO(decoded.decode("utf-8")))
        elif "xls" in filename:
            # Assume that the user uploaded an excel file
            df = pd.read_excel(io.BytesIO(decoded))
    except Exception as e:
        return None
    return df

@app.callback(
    dash.dependencies.Output("DataFrame", "children"),
                      [Input("upload-data", "contents"),
                       Input("upload-data", "filename")])
def Transform_Data(contents, filename):
    if contents is not None:
        Data = parse_contents(contents, filename)
        if Data is not None:
            return Data.to_json(date_format="iso", orient="split")

@app.callback(
    dash.dependencies.Output("Column_Names1", "options"),
                      [Input("DataFrame", "children")])
def RadioItem_Options(Data):
    df = pd.read_json(Data, orient="split").sort_index(axis=1)
    if df.empty:
        return []
    else:
        return [{"label": i, "value": i} for i in list(df.columns.values)]

@app.callback(
    dash.dependencies.Output("New_Input", "children"),
                      [Input("DataFrame", "children")])
def Output_New_Input(Data):
    if Data == None:
        return []
    else:
        return New_Input

if __name__ == "__main__":
    app.run_server(debug=True)

For my actual work I have already got round the problem by turning New_Input into a function and then combining the Output_New_Input and RadioItem_Options into a single callback.

Also it seems that sometimes it takes multiple uploads to populate the RadioItem.

Many Thanks for all your sterling work