Adding in a dropdown for every column, without hard coding in the columns?

Hi all,

I’m sorry in advance. I usually use StackOverflow, please let me know if I have asked a question in the wrong place (I thought here would be more appropriate).

I have a data set that looks like this:

cat_id author year publisher country value (dollars)
name1 kunga 1998 D and D Australia 10
name2 siba 2001 D and D UK 20
name3 siba 2001 D and D US 20
name3 shevara 2001 D and D UK 10
name3 dougherty 1992 D and D Australia 20
name4 ken 2011 S and K Australia 10

I want to turn this into a table in plotly dash. I have most of the code that I want set up:

#!/usr/bin/env python
import dash
from dash.dependencies import Input, Output, State
import dash_table
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd

app = dash.Dash(__name__)
df = pd.read_excel('dash_test_doc.xlsx')


app.layout = html.Div([
    html.Div([
        dcc.Input(
            id='adding-rows-name',
            placeholder='Enter a column name...',
            value='',
            style={'padding': 10},
        ),
        html.Button('Add Column', id='adding-rows-button', n_clicks=0)
    ], style={'height': 50}),



     dash_table.DataTable(
         id='adding-rows-table',
         columns=[{"name": i, "id": i} for i in df.columns],
         data = df.to_dict('rows'),
         editable=True,
         filtering=True,
         sorting=True,
         sorting_type="multi",
         row_selectable="multi",
         row_deletable=True,
         selected_rows=[],
         pagination_mode="fe",
         style_cell_conditional=[
         {
             'if': {'row_index': 'odd'},
             'backgroundColor': 'rgb(230, 255, 230)'
         }
     ] + [
         {
             'if': {'column_id': c},
             'textAlign': 'left'
        } for c in ['Date', 'Region']
    ],
    style_header={
        'backgroundColor': 'white',
        'fontWeight': 'bold'
    }
    ),

    html.Button('Add Row', id='editing-rows-button', n_clicks=0),
    dcc.Graph(id='adding-rows-graph'),
])

@app.callback(
    Output('adding-rows-table', 'data'),
    [Input('editing-rows-button', 'n_clicks')],
    [State('adding-rows-table', 'data'),
     State('adding-rows-table', 'columns')])
def add_row(n_clicks, rows, columns):
    if n_clicks > 0:
        rows.append({c['id']: '' for c in columns})
    return rows


@app.callback(
    Output('adding-rows-table', 'columns'),
    [Input('adding-rows-button', 'n_clicks')],
    [State('adding-rows-name', 'value'),
     State('adding-rows-table', 'columns')])
def update_columns(n_clicks, value, existing_columns):
    if n_clicks > 0:
        existing_columns.append({
            'id': value, 'name': value,
            'editable_name': True, 'deletable': True
        })
    return existing_columns


@app.callback(
    Output('adding-rows-graph', 'figure'),
    [Input('adding-rows-table', 'data'),
     Input('adding-rows-table', 'columns')])
def display_output(rows, columns):
    return {
        'data': [{
            'type': 'heatmap',
            'z': [[row.get(c['id'], None) for c in columns] for row in rows],
            'x': [c['name'] for c in columns]
        }]
    }


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

There is just three things that I’m struggling with if someone could help I would appreciate it:

  1. I want to create a dropdown menu for each column, without pre-defining the dropdown options. for example using the table here, in publisher, there are two choices (D and D, and S and K); i want those to automatically appear as a dropdown option to filter by, without having to hardcode them in, because for example if I edit the input table and add a row, and there’s another publisher added (e.g. A and D), i want A and D to automatically be added to the dropdown options? (so ultimately, the idea would be to mimic excel, where I could select from a dropdown e.g. D and D and S and K from a dropdown for this column, and the entries would be filtered based on this).

  2. is it possible to select multiple rows, and delete them with one action? at the minute, I can delete single rows.

  3. Is it possible to export the table? e.g. say I read in a table, and then someone deletes some columns/rows, can I export the resulting table?

If anyone could help me figure out the code for these I’d appreciate it. As a a side note, since I’m just starting out, if anyone has any other suggestions for improvements to this script I’d appreciate it.