Dropdown menu won't display options but appears to be updating from callback

I want to upload any csv and have a dropdown menu that populates the column names as the options.

The size of the dropdown menu is changing everytime I upload a csv so something is getting passed to it, but it won’t display any of the options. Am I doing something wrong or is this a bug?

Any help is much appreciated!

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([
    
    html.H1("Model Builder", style={'text-align': 'center'}),
    
    dcc.Upload(
        id='datatable-upload',
        children=html.Div([
            'Drag and Drop or ',
            html.A('Select Files')
        ]),
        style={
            'width': '100%', 'height': '60px', 'lineHeight': '60px',
            'borderWidth': '1px', 'borderStyle': 'dashed',
            'borderRadius': '5px', 'textAlign': 'center', 'margin': '10px'
        },
    ),
    
        html.Br(),
    
    html.H5("Sample Data", style={'text-align': 'center'}),
    
        html.Br(),
    
    dash_table.DataTable(id='datatable-upload-container'),
    
        html.Br(),
    
    html.H5("Summary Statistics", style={'text-align': 'center'}),
    
        html.Br(),
    
    dash_table.DataTable(id='summary_stats'),
    
        html.Br(),
    
       html.H5("Data Types", style={'text-align': 'center'}),
    
        html.Br(),
    
    dash_table.DataTable(id='data-types'),
    
        html.Br(),

    
    html.H5("Graph Me", style={'text-align': 'center'}),
        
        html.Br(),
    
    dcc.Dropdown(id="variables"),
    
        html.Br(),
    
    dcc.Graph(id='datatable-upload-graph')
    
])


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

#---------------------------------------------------------------------------------------------
# Sample data

@app.callback(Output('datatable-upload-container', 'data'),
              Output('datatable-upload-container', 'columns'),
              Input('datatable-upload', 'contents'),
              State('datatable-upload', 'filename'))
def update_output(contents, filename):
    if contents is None:
        return [{}], []
    df = parse_contents(contents, filename)
    return df.head().to_dict('records'), [{"name": i, "id": i} for i in df.columns]

#----------------------------------------------------------------------------------------------
#Summary stats

@app.callback(Output('summary_stats', 'data'),
              Output('summary_stats', 'columns'),
              Input('datatable-upload', 'contents'),
              State('datatable-upload', 'filename'))

def update_output(contents, filename):
    if contents is None:
        return [{}], []
    df = parse_contents(contents, filename)
    dff = df.describe().round(2).transpose()
    dff.reset_index(inplace = True)
    datatypes = df.dtypes
    print(datatypes)
    dff['dataType'] = datatypes
    return dff.to_dict('records'), [{"name": i, "id": i} for i in dff.columns]

#----------------------------------------------------------------------------------------------
#Data type 

@app.callback(Output('data-types', 'data'),
              Output('data-types', 'columns'),
              Input('datatable-upload', 'contents'),
              State('datatable-upload', 'filename'))

def update_output(contents, filename):
    if contents is None:
        return [{}], []
    df = parse_contents(contents, filename)
    dff = df.dtypes
    return dff.to_json(), [{"name": i, "id": i} for i in dff.columns]

#----------------------------------------------------------------------------------------------
#Dropdown to select histogram variable - options won't display but they appear to populate

@app.callback(Output('variables', 'options'),
              Input('datatable-upload', 'contents'),
              State('datatable-upload', 'filename'))
              
def update_output(contents, filename):
    if contents is None:
        return [{}], []
    df = parse_contents(contents, filename)
    cols = [{"name": i, "id": i} for i in df.columns]
    print(cols)
    type(cols)
    return cols

#----------------------------------------------------------------------------------------------
#histogram  - not connected
@app.callback(Output('datatable-upload-graph', 'figure'),
              Input('datatable-upload-container', 'data'))
def display_graph(rows):
    df = pd.DataFrame(rows)

    if (df.empty or len(df.columns) < 1):
        return {
            'data': [{
                'x': [],
                'y': [],
                'type': 'bar'
            }]
        }
    return {
        'data': [{
            'x': df[df.columns[0]],
            'y': df[df.columns[1]],
            'type': 'bar'
        }]
    }
#----------------------------------------------------------------------------------------------

if __name__ == '__main__':
    app.run_server(debug=False)

Hi @helpMe,

Is the line ‘print(cols)’ showing you the right data (dictionary)?

Yes I believe the dictionary is correct.

Just realised I had the key and value labelled incorrectly. Its working now I have changed it to Label and value.

1 Like