Black Lives Matter. Please consider donating to Black Girls Code today.

Failed component prop type - "columns"

Hello!

I’m trying to create a dashboard and used the dash user guide for ‘Backend Paging with Filtering and Multi-Column Sorting’ (https://dash.plot.ly/datatable/callbacks) to set it up, and it worked.

However, I also wanted it to update based on my changes to my csv, and so used dcc.Interval according to the code written by user waly01 here (Dash app not reading modified file on refreshing the browser).

Due to already having an output with the same name, I merged one of the callbacks with the callback in the code of the dash user guide for backend paging above, but when I launch my app, I am met with this error that I’m fairly sure is linked to my second callback

Failed component prop type: Invalid component prop columns[0] key names supplied to DataTable.
Bad object: {
“id”: “Activity”,
“names”: “Activity”
}
Valid keys: [
“clearable”,
“deletable”,
“editable”,
“hideable”,
“renamable”,
“selectable”,
“format”,
“id”,
“name”,
“presentation”,
“on_change”,
“sort_as_null”,
“validation”,
“type”
]

Here is my code itself.

df = pd.read_csv(‘data/dashboard_data.csv’)

PAGE_SIZE = 10

app.layout = html.Div(
[
dash_table.DataTable(
id=‘table-sorting-filtering’,
columns=[
{‘name’: i, ‘id’: i, ‘deletable’: True} for i in sorted(df.columns)
],
page_current= 0,
page_size= PAGE_SIZE,
page_action=‘custom’,

        filter_action='custom',
        filter_query='',

        sort_action='custom',
        sort_mode='multi',
        sort_by=[],
    ),
    dcc.Interval(id='interval_component', interval = 10000, n_intervals=0)
]

)

operators = [['ge ', ‘>=’],
['le ', ‘<=’],
['lt ', ‘<’],
['gt ', ‘>’],
['ne ', ‘!=’],
['eq ', ‘=’],
['contains '],
['datestartswith ']]

def split_filter_part(filter_part):
for operator_type in operators:
for operator in operator_type:
if operator in filter_part:
name_part, value_part = filter_part.split(operator, 1)
name = name_part[name_part.find(’{’) + 1: name_part.rfind(’}’)]
value_part = value_part.strip()
v0 = value_part[0]
if (v0 == value_part[-1] and v0 in ("’", ‘"’, ‘`’)):
value = value_part[1: -1].replace(’\’ + v0, v0)

            else:
                try:
                    value = float(value_part)
                except ValueError:
                    value = value_part
            # word operators need spaces after them in the filter string,
            # but we don't want these later
            return name, operator_type[0].strip(), value
return [None] * 3

@app.callback(
Output(‘table-sorting-filtering’, ‘data’),
[Input(‘table-sorting-filtering’, “page_current”),
Input(‘table-sorting-filtering’, “page_size”),
Input(‘table-sorting-filtering’, ‘sort_by’),
Input(‘table-sorting-filtering’, ‘filter_query’),
Input(‘interval_component’, ‘n_intervals’)])

def update_table(page_current, page_size, sort_by, filter, n_intervals):
filtering_expressions = filter.split(’ && ')
dff = df
for filter_part in filtering_expressions:
col_name, operator, filter_value = split_filter_part(filter_part)
if operator in (‘eq’, ‘ne’, ‘lt’, ‘le’, ‘gt’, ‘ge’):
# these operators match pandas series operator method names
dff = dff.loc[getattr(dff[col_name], operator)(filter_value)]
elif operator == ‘contains’:
dff = dff.loc[dff[col_name].str.contains(filter_value)]
elif operator == ‘datestartswith’:

        # this is a simplification of the front-end filtering logic,
        # only works with complete fields in standard format
        dff = dff.loc[dff[col_name].str.startswith(filter_value)]

if len(sort_by):
    dff = dff.sort_values(
        [col['column_id'] for col in sort_by],
        ascending=[
            col['direction'] == 'asc'
            for col in sort_by
        ],
        inplace=False
    )
page = page_current
size = page_size
return dff.iloc[page * size: (page + 1) * size].to_dict('records')

def update_rows(n_intervals, n_clicks):
data = pd.read_csv(‘data/dashboard_data.csv’)
dict = data.to_dict(‘records’)
return dict

@app.callback(
Output(‘table-sorting-filtering’, ‘columns’),
[Input(‘interval_component’, ‘n_intervals’)]
)
def update_cols(n_intervals):
data = pd.read_csv(‘data/dashboard_data.csv’)
columns = [
{‘id’: i, ‘names’: i} for i in data.columns
]

return columns

if name == ‘main’:
app.run_server(debug=True)

The bolded parts are the callback that i added into my original callback, i think it’s fine. The seperate blockquote about columns is where I think the issue is.

Please help if you have any idea

looks like a typo - you supplied “names” but the property is actually “name”

1 Like

Thank you! That was the issue!

1 Like