This is what ended up working for me. Hope it helps!
.
.
.
def create_table_card(self, id):
return dbc.Card(
children = [
html.Div(
dash_table.DataTable(
id = id,
data = [
dict(filename = '', waveform = '', expression = '', result = ''),
dict(filename = '', waveform = '', expression = '', result = ''),
dict(filename = '', waveform = '', expression = '', result = '')
],
columns = [
{ 'id': 'filename', 'name': 'Filename', 'presentation': 'dropdown'},
{ 'id': 'waveform', 'name': 'Waveform', 'presentation': 'dropdown'},
{ 'id': 'expression', 'name': 'Expression', 'editable': True },
{ 'id': 'result', 'name': 'Result', 'editable': False }
],
style_cell = {
'textAlign' : 'center',
'fontSize' : 14,
'font-family' :'sans-serif'
},
editable = True,
row_deletable = True
),
style = {
'padding-top' : 25,
'padding-bottom' : 20,
'padding-left' : 35,
'padding-right' : 35
}
),
html.Div(
dbc.Button('Add Row', id = 'table-add-row-button', className = 'ml-auto', n_clicks = 0),
style = {
'padding-left' : 20,
'padding-bottom' : 20
}
)
]
)
.
.
.
@app.callback(
Output('table', 'dropdown'),
[
Input('table', 'data_timestamp')
],
[
State('table', 'data')
]
)
def table_dropdown(timestamp, rows):
logging.debug('table_dropdown')
return { 'filename' : { 'options': get_uploads() } }
@app.callback(
Output('table', 'dropdown_conditional'),
[
Input('table', 'data_timestamp')
],
[
State('table', 'data')
]
)
def table_dropdown_conditional(timestamp, rows):
logging.debug('rows = {}'.format(rows))
filenames = []
for row in rows:
if row['filename'] is not None:
if os.path.isfile(os.path.join(FOLDER_UPLOADS, row['filename'])):
filenames.append(row['filename'])
# logging.debug('filenames = {}'.format(filenames))
conditions = []
for filename in set(filenames):
d = None
if filename.endswith('.feather'):
d = pd.read_feather(os.path.join(FOLDER_UPLOADS, filename))
elif filename.endswith('.parquet'):
# NOTE: By using Dask (dd) instead of Pandas (pd) below, we avoid
# loading all of the data when all we need are the column names.
# Unfortunately, Dask doesn't support feather right now.
d = dd.read_parquet(os.path.join(FOLDER_UPLOADS, filename))
if d is not None:
conditions.append({
'if' : {
'column_id' : 'waveform',
'filter_query' : '{filename} eq \'' + filename + '\''
},
'options' : [ { 'label': i, 'value': i } for i in d.columns[1:] ]
})
# logging.debug('conditions = {}'.format(conditions))
return conditions
@app.callback(
Output('table', 'data'),
[
Input('table-add-row-button', 'n_clicks'),
Input('table', 'data_timestamp')
],
[
State('table', 'data'),
State('table', 'columns')
]
)
def table(n, timestamp, rows, columns):
context = dash.callback_context
context = context.triggered[0]['prop_id'].split('.')[0] if context.triggered else None
logging.debug('context = {}'.format(context))
# If the user clicked the Add Row button, then add an empty row:
if context == 'table-add-row-button':
rows.append({ column['id']: '' for column in columns })
# If the user cleared a filename, then clear the associated waveform:
if context == 'table':
for row in rows:
if row['filename'] is None:
row['waveform'] = ''
return rows