Open shavavo opened 5 years ago
I run into the same issue, with a very similar stack trace, but only when I add the property
filter_action = 'native'
to my DataTable.
Anyone have an idea what might be breaking? Below is the part of my code where I create the DataTable. The app, including the table, works fine if I remove the filter_action property.
dash_table.DataTable( id = 'files-table', columns = files_table_columns, data = [], row_selectable = 'multi', row_deletable = True, editable = False, dropdown = {}, sort_action = 'native', filter_action = 'native', style_header = { 'backgroundColor': 'rgb(230, 230, 230)', 'fontWeight': 'bold' }, style_table = { 'maxHeight': '300px', 'overflowY': 'scroll' }, fixed_rows = { 'headers': True, 'data': 0 } ),
Incidentally I just found that the filtering action works fine if I remove the lines
row_selectable = 'multi',
row_deletable = True,
So it seems like something about the combination of selectable AND deletable rows AND the filter_action is resulting in the problem.
@Marc-Andre-Rivet seems to me that this could be related to #447
@rp2532 I have created a table with editable=True and filter_action=native. When I try and add in row_deletable=True or row_selectable=True, the table does not render.
It seems that having filter_action=native in combination with (row_deletable=True OR row_selectable="multi") is not possible, like you are seeing.
I'm also having a problem with the combination of row_selectable=multi
and filter_action=native
. getting the same error Cannot read property '0' of undefined
. developer tools shows this in details:
(This error originated from the built-in JavaScript code that runs Dash apps. Click to see the full stack trace or open your browser's console.)
TypeError: Cannot read property '0' of undefined
at e.getWeight (http://localhost:3000/_dash-component-suites/dash_table/async-table.v4_6_1m1582839172.js:7:117699)
at http://localhost:3000/_dash-component-suites/dash_table/async-table.v4_6_1m1582839172.js:7:131047
at http://localhost:3000/_dash-component-suites/dash_table/async-table.v4_6_1m1582839172.js:7:197843
at http://localhost:3000/_dash-component-suites/dash_table/async-table.v4_6_1m1582839172.js:1:427
at Object.t [as a] (http://localhost:3000/_dash-component-suites/dash_table/bundle.v4_6_1m1583158233.js:1:6127)
at e.value (http://localhost:3000/_dash-component-suites/dash_table/async-table.v4_6_1m1582839172.js:7:131008)
at http://localhost:3000/_dash-component-suites/dash_table/async-table.v4_6_1m1582839172.js:7:129754
at e.memoizedCreateEdges (http://localhost:3000/_dash-component-suites/dash_table/bundle.v4_6_1m1583158233.js:1:10407)
at e.value (http://localhost:3000/_dash-component-suites/dash_table/async-table.v4_6_1m1582839172.js:7:131814)
at t.tableFn (http://localhost:3000/_dash-component-suites/dash_table/async-table.v4_6_1m1582839172.js:7:156594)
dash used is as follows on python 3.8.1:
dash==1.9.1
dash-core-components==1.8.1
dash-cytoscape==0.1.1
dash-html-components==1.0.2
dash-renderer==1.2.4
dash-table==4.6.1
@wolfgangpfnuer i went through the same problem and i realized that if i create my DataTable using an empty pandas DataFrame with one column, it works. Try it yourself, for example:
This one will throw the "Cannot read property '0' of undefined" error:
import dash
import dash_table
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/solar.csv')
app = dash.Dash(__name__)
app.layout = html.Div(children=[
dash_table.DataTable(
id='table',
filter_action='native',
row_selectable="single"
),
html.Div(id='dummy_input')
])
@app.callback(Output('table', 'columns'), [Input('dummy_input', 'children')])
def update_columns(dummy):
return [{"name": i, "id": i} for i in df.columns]
@app.callback(Output('table', 'data'), [Input('dummy_input', 'children')])
def update_data(dummy):
return df.to_dict('records')
if __name__ == '__main__':
app.run_server(debug=True)
However, this one works:
import dash
import dash_table
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/solar.csv')
app = dash.Dash(__name__)
start_table_df = pd.DataFrame(columns=['Start Column']) ####### inserted line
app.layout = html.Div(children=[
dash_table.DataTable(
data=start_table_df.to_dict('records'), ####### inserted line
columns = [{'id': c, 'name': c} for c in start_table_df.columns], ####### inserted line
id='table',
filter_action='native',
row_selectable='single'
),
html.Div(id='dummy_input')
])
@app.callback(Output('table', 'columns'), [Input('dummy_input', 'children')])
def update_columns(dummy):
return [{"name": i, "id": i} for i in df.columns]
@app.callback(Output('table', 'data'), [Input('dummy_input', 'children')])
def update_data(dummy):
return df.to_dict('records')
if __name__ == '__main__':
app.run_server(debug=True)
@montovaneli I cannot reproduce your workaround - if I have a data_table with BOTH filter_action and row_selectable enabled, I get the error upon startup that says
TypeError: Cannot read property '0' of undefined
However, if only one of filter_action or row_selectable is used (or neither of them), the error does not appear.
Code below is modified from keval's post on this page - https://community.plotly.com/t/datatable-fails-to-update-on-callback/32720/4
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
import dash_table
from plotly.subplots import make_subplots
import os
import numpy as np
import pandas as pd
import io
import base64
# Empty DataFrame to start the DataTable (workaround for bug in DataTable - https://github.com/plotly/dash-table/issues/436#issuecomment-615924723)
start_table_df = pd.DataFrame(columns=['Start Column'])
# Create dash app
app = dash.Dash(__name__)
### LAYOUT ###
# App Layout
app.layout = html.Div([
html.H3("Post Covid-19 Tool"),
dcc.Upload(
id='upload-data',
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'
},
# Allow multiple files to be uploaded
multiple=False
),
html.Div([
dash_table.DataTable(
data=start_table_df.to_dict('records'),
columns = [{'id': c, 'name': c} for c in start_table_df.columns],
id='emp-table',
#page_size = 14,
#sort_action='native',
filter_action='native',
row_selectable='single',
#row_deletable=True,
#editable=True
),
])
])
# file upload function
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:
print(e)
return None
return df
### CALLBACKS ###
# Callback: Return Datatable
@app.callback([Output('emp-table', 'data'),
Output('emp-table', 'columns')],
[Input('upload-data', 'contents')],
[State('upload-data', 'filename')])
def render_table(contents, filename):
if contents and filename:
df_geo = parse_contents(contents, filename)
columns = [{"name": i, "id": i} for i in df_geo.columns]
data = df_geo.to_dict('records')
# Debug
print(df_geo.head())
return data, columns
else:
return [], []
if __name__ == '__main__':
app.run_server(debug=True, port=8000)
@Marc-Andre-Rivet @chriddyp Any insight into this issue, i.e. why filter_action does not work in combination with either row_selectable or editable or row_deletable? Any idea when it might be fixed?
Incidentally a related issue on the community forum is in keval's comment on this page - https://community.plotly.com/t/datatable-fails-to-update-on-callback/32720/5
@rp2532 that is because you are returning empty lists when you don't have uploaded data. Try this:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
import dash_table
from plotly.subplots import make_subplots
import os
import numpy as np
import pandas as pd
import io
import base64
# Empty DataFrame to start the DataTable (workaround for bug in DataTable - https://github.com/plotly/dash-table/issues/436#issuecomment-615924723)
start_table_df = pd.DataFrame(columns=[''])
# Create dash app
app = dash.Dash(__name__)
### LAYOUT ###
# App Layout
app.layout = html.Div([
html.H3("Post Covid-19 Tool"),
dcc.Upload(
id='upload-data',
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'
},
# Allow multiple files to be uploaded
multiple=False
),
html.Div([
dash_table.DataTable(
data=start_table_df.to_dict('records'),
columns = [{'id': c, 'name': c} for c in start_table_df.columns],
id='emp-table',
#page_size = 14,
#sort_action='native',
filter_action='native',
row_selectable='single',
#row_deletable=True,
#editable=True
),
])
])
# file upload function
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:
print(e)
return None
return df
### CALLBACKS ###
# Callback: Return Datatable
@app.callback([Output('emp-table', 'data'),
Output('emp-table', 'columns')],
[Input('upload-data', 'contents')],
[State('upload-data', 'filename')])
def render_table(contents, filename):
if contents and filename:
df_geo = parse_contents(contents, filename)
columns = [{"name": i, "id": i} for i in df_geo.columns]
data = df_geo.to_dict('records')
# Debug
print(df_geo.head())
return data, columns
else:
return start_table_df.to_dict('records'), [{'id': '', 'name': ''}]
if __name__ == '__main__':
app.run_server(debug=True, port=8000)
@montovaneli Confirming, that indeed works!
Same issue here and @montovaneli's workaround did the trick as well. Thanks!
Just to provide more color on this.
It appears that having columns
set to an empty list on the examples above will reproduce this error.
On the other hand data
can be set to an empty list.
DataTable with row_selectable="multi" does not respond to any columns or data callbacks.
Debug shows Javascript error:
Example: