Display tables in Dash


#42

Good suggestion! I just add preliminary support for this in the latest version.

The latest version (v0.5.0) fixes several bugs and adds support for simultaneous row-selection, filtering, and sorting:


#43

Hi!
First of all, thanks for this great features! :slight_smile:
I was wondering, is it possible to:

  • insert links into a column?
  • export table as a csv?

Thanks!


#44

See Download raw data

Not possible right now, but tracking in https://github.com/plotly/dash-table-experiments/issues/6


#45

Thanks! :slight_smile:


#46

Hi Chris. This might be a bit pie in the sky. But what would be great would be to use dash core components in the table itself. Ideally, you could specify a column as a dropdown menu with the options the same for each row, and then you would pass in the value of each row as normal.


#47

@chriddyp
If i add the hidden element to the main page layout, then i am getting the following error along with “Error loading layout” on the browser -

Blockquote
[pratik@bi-insightslab apps]$ uwsgi --http :8888 --wsgi-file /home/pratik/tools/apps/index.py --callable server --master --processes 1 --threads 4
*** Starting uWSGI 2.0.15 (64bit) on [Wed Sep 20 18:39:58 2017] ***
compiled with version: 4.4.7 20120313 (Red Hat 4.4.7-18) on 24 August 2017 01:08:04
os: Linux-2.6.32-696.1.1.el6.centos.plus.x86_64 #1 SMP Wed Apr 12 00:10:12 UTC 2017
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on :8888 fd 4
uwsgi socket 0 bound to TCP address 127.0.0.1:41455 (port auto-assigned) fd 3
Python version: 2.7.12 (default, Jun 28 2016, 17:49:40) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]
Python main interpreter initialized at 0x1d7ac60
python threads support enabled
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 207360 bytes (202 KB) for 4 cores
*** Operational MODE: threaded ***
WSGI app 0 (mountpoint=’’) ready in 204 seconds on interpreter 0x1d7ac60 pid: 85492 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 85492)
spawned uWSGI worker 1 (pid: 85858, cores: 4)
spawned uWSGI http 1 (pid: 85859)
[pid: 85858|app: 0|req: 1/1] 121.244.34.250 () {38 vars in 928 bytes} [Wed Sep 20 18:43:32 2017] GET / => generated 568 bytes in 5 msecs (HTTP/1.1 200) 6 headers in 447 bytes (1 switches on core 0)
[2017-09-20 18:43:34,019] ERROR in app: Exception on /_dash-layout [GET]
Traceback (most recent call last):
File “/usr/lib/python2.7/site-packages/flask/app.py”, line 1982, in wsgi_app
response = self.full_dispatch_request()
File “/usr/lib/python2.7/site-packages/flask/app.py”, line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File “/usr/lib/python2.7/site-packages/flask/app.py”, line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File “/usr/lib/python2.7/site-packages/flask/app.py”, line 1612, in full_dispatch_request
rv = self.dispatch_request()
File “/usr/lib/python2.7/site-packages/flask/app.py”, line 1598, in dispatch_request
return self.view_functionsrule.endpoint
File “/usr/lib/python2.7/site-packages/dash/dash.py”, line 156, in serve_layout
cls=plotly.utils.PlotlyJSONEncoder),
File “/usr/lib64/python2.7/json/init.py”, line 251, in dumps
sort_keys=sort_keys, **kw).encode(obj)
File “/usr/lib/python2.7/site-packages/plotly/utils.py”, line 136, in encode
encoded_o = super(PlotlyJSONEncoder, self).encode(o)
File “/usr/lib64/python2.7/site-packages/simplejson/encoder.py”, line 275, in encode
chunks = self.iterencode(o, _one_shot=True)
File “/usr/lib64/python2.7/site-packages/simplejson/encoder.py”, line 357, in iterencode
return _iterencode(o, 0)
File “/usr/lib/python2.7/site-packages/plotly/utils.py”, line 201, in default
return encoding_method(obj)
File “/usr/lib/python2.7/site-packages/plotly/utils.py”, line 210, in encode_as_plotly
return obj.to_plotly_json()
TypeError: unbound method to_plotly_json() must be called with DataTable instance as first argument (got nothing instead)
[pid: 85858|app: 0|req: 2/2] 121.244.34.250 () {42 vars in 981 bytes} [Wed Sep 20 18:43:34 2017] GET /_dash-layout => generated 291 bytes in 4 msecs (HTTP/1.1 500) 2 headers in 84 bytes (1 switches on core 1)
[pid: 85858|app: 0|req: 4/3] 121.244.34.250 () {38 vars in 910 bytes} [Wed Sep 20 18:43:34 2017] GET /favicon.ico => generated 568 bytes in 4 msecs (HTTP/1.1 200) 5 headers in 264 bytes (1 switches on core 2)
[pid: 85858|app: 0|req: 4/4] 121.244.34.250 () {42 vars in 993 bytes} [Wed Sep 20 18:43:34 2017] GET /_dash-dependencies => generated 553 bytes in 6 msecs (HTTP/1.1 200) 5 headers in 256 bytes (1 switches on core 3)
Blockquote

If am removing the hidden element then the rest of layout is being loaded correctly


#48

The main page layout code is as follows -


from dash.dependencies import Input, Output
import dash_table_experiments as dt
import dash_core_components as dcc
import dash_html_components as html

from app import app,server
import toc, visibility, pricing, whatifscenario

app.layout = html.Div([
dcc.Location(id=‘url’, refresh=False),
html.Div(dt.DataTable, style={‘display’: ‘none’}),
html.Div(
dcc.Tabs(
tabs=[
{‘label’: ‘Table of Contents’, ‘value’: 1},
{‘label’: ‘Visibility Elasticity’, ‘value’: 2},
{‘label’: ‘Pricing Elasticity’, ‘value’: 3},
{‘label’: ‘What if Scenario’, ‘value’: 4},
],
value=1,
id=‘tabs’,
vertical=True,
style={
‘height’: ‘100vh’,
‘borderRight’: ‘thin lightgrey solid’,
‘textAlign’: ‘left’
}
),
style={‘width’: ‘20%’, ‘float’: ‘left’}
),
html.Div(html.Div(id=‘tab-output’),style={‘width’: ‘80%’, ‘float’: ‘right’})

],style={
‘fontFamily’: ‘Sans-Serif’,
‘margin-left’: ‘auto’,
‘margin-right’: ‘auto’,
}
)

@app.callback(Output(‘url’, ‘pathname’),
[Input(‘tabs’, ‘value’)])
def display_page(value):
if value == 2:
return '/visibility’
elif value == 3:
return '/pricing’
elif value == 4:
return '/whatif’
else:
return ‘/’

@app.callback(Output(‘tab-output’, ‘children’),
[Input(‘url’, ‘pathname’)])
def display_page(pathname):
if pathname == ‘/visibility’:
return visibility.layout
elif pathname == ‘/pricing’:
return pricing.layout
elif pathname==’/whatif’:
return whatifscenario.layout
else:
return toc.layout

if name == ‘main’:
server.run()



#49

try html.Div(dtable.DataTable(rows=[{}]), style={‘display’: ‘none’})


#50

Thanks for the clarification. It worked. :smiley:


#51

Hi Chris,

When do you think you will merge table code into the core components?

I’m looking to use the editable table feature, where could i read more about it?

Thanks, Dave


#52

Undefined timeline right now, still soliciting feedback from the community and from our Plotly On-Premise customers.

However, you can use this today by following the instructions in https://github.com/plotly/dash-table-experiments. Follow this thread or the CHANGELOG.md file for changes and note that backwards incompatible changes may be made.

I just created a simple example that uses editable=True. You can check it out here: https://github.com/plotly/dash-table-experiments/blob/master/usage-editable.py


#53

Chris, thanks for the prompt reply. I plan on using it and I will give you feedback on it.


#54

Hi Chris,

I’m attempting to use the dash-table-experiments example you provided while combining it with what you’ve accomplished with tabs.

I’m able to recreate your usage.py without issue on its own and have had no issues creating apps with tabs. However, when I attempt to package the app.layout from your example into a ‘children Div’ to show when clicking a tab, the platform hangs and cannot switch between tabs… nor does it show the table and graphs.

Here is the full code:

'import dash
’from dash.dependencies import Input, Output, State
’import dash_core_components as dcc
’import dash_html_components as html
’import dash_table_experiments as dt
’import pandas as pd
’import plotly

'app = dash.Dash()

'app.scripts.config.serve_locally = True
’app.config.supress_callback_exceptions = True

‘DF_GAPMINDER = pd.read_csv(
’ ‘https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv
)
'DF_GAPMINDER = DF_GAPMINDER[DF_GAPMINDER[‘year’] == 2007]
'DF_GAPMINDER.loc[0:20]

'test_layout = html.Div([

’ html.H4(‘Gapminder DataTable’),
’ dt.DataTable(
’ rows=DF_GAPMINDER.to_dict(‘records’),

’ # optional - sets the order of columns
’ columns=sorted(DF_GAPMINDER.columns),

’ row_selectable=True,
’ filterable=True,
’ sortable=True,
’ selected_row_indices=[],
’ id=‘datatable-gapminder’
’ ),
’ html.Div(id=‘selected-indexes’),
’ dcc.Graph(
’ id=‘graph-gapminder’
’ ),
’], className=“container”)

‘app.layout = html.Div([

’ html.Div([
’ html.Div(
’ dcc.Tabs(
’ tabs=[
’ {‘label’:‘First View’, ‘value’:1},
’ {‘label’:‘Second View’, ‘value’:2},
’ {‘label’:‘Third View’, ‘value’:3}
’ ],
’ value=1,
’ id=‘overall-tabs’,
’ vertical=False,
’ style={
’ ‘borderRight’:‘thin lightgrey solid’,
’ ‘textAlign’:‘left’
’ }
’ ),
’ style={‘width’:‘100%’, ‘float’:‘top’}
’ ),
’ html.Div(
’ html.Div(id=‘tab-output’),
’ style={‘width’:‘100%’, ‘float’:‘bottom’}
’ )
’ ],
’ style={‘fontFamily’:‘Dosis’,
’ }),

'# test_layout"""

'])

@app.callback(
’ dash.dependencies.Output(‘tab-output’, ‘children’),
’ [dash.dependencies.Input(‘overall-tabs’, ‘value’)])
‘def display_content(overall_tab):
’ if overall_tab == 1:
’ return html.Div([])
’ elif overall_tab == 2:
’ return html.Div([])
’ elif overall_tab == 3:
’ return test_layout

@app.callback(
’ Output(‘datatable-gapminder’, ‘selected_row_indices’),
’ [Input(‘graph-gapminder’, ‘clickData’)],
’ [State(‘datatable-gapminder’, ‘selected_row_indices’)])
‘def update_selected_row_indices(clickData, selected_row_indices):
’ print ‘make it here?’
’ if clickData:
’ for point in clickData[‘points’]:
’ if point[‘pointNumber’] in selected_row_indices:
’ selected_row_indices.remove(point[‘pointNumber’])
’ else:
’ selected_row_indices.append(point[‘pointNumber’])
’ return selected_row_indices

@app.callback(
’ Output(‘graph-gapminder’, ‘figure’),
’ [Input(‘datatable-gapminder’, ‘rows’),
’ Input(‘datatable-gapminder’, ‘selected_row_indices’)])
‘def update_figure(rows, selected_row_indices):
’ dff = pd.DataFrame(rows)
’ fig = plotly.tools.make_subplots(
’ rows=3, cols=1,
’ subplot_titles=(‘Life Expectancy’, ‘GDP Per Capita’, ‘Population’,),
’ shared_xaxes=True)
’ marker = {‘color’: [’#0074D9’]*len(dff)}
’ for i in (selected_row_indices or []):
’ marker[‘color’][i] = ‘#FF851B
’ fig.append_trace({
’ ‘x’: dff[‘country’],
’ ‘y’: dff[‘lifeExp’],
’ ‘type’: ‘bar’,
’ ‘marker’: marker
’ }, 1, 1)
’ fig.append_trace({
’ ‘x’: dff[‘country’],
’ ‘y’: dff[‘gdpPercap’],
’ ‘type’: ‘bar’,
’ ‘marker’: marker
’ }, 2, 1)
’ fig.append_trace({
’ ‘x’: dff[‘country’],
’ ‘y’: dff[‘pop’],
’ ‘type’: ‘bar’,
’ ‘marker’: marker
’ }, 3, 1)
’ fig[‘layout’][‘showlegend’] = False
’ fig[‘layout’][‘height’] = 800
’ fig[‘layout’][‘margin’] = {
’ ‘l’: 40,
’ ‘r’: 10,
’ ‘t’: 60,
’ ‘b’: 200
’ }
’ fig[‘layout’][‘yaxis3’][‘type’] = ‘log’
’ return fig

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

I know test_layout produces the original display, it can be shown by uncommenting test_layout within app.layout and commenting the tabs related Div above it. Interestingly, if I try to use both at once, I get test_layout showing up as a tab and as its separate Div.

Any ideas on why it will not show within a tab without including it as its own Div?

Thanks for all the help, great product!


#55

@smcelrea - I suspect that this the same issue as in this comment. Could see if the recommendation in that comment fixes your issue? Thanks for reporting! :slight_smile:


#56

This worked, thanks so much! Apologies for not coming across that comment during the first read.


#57

2 posts were split to a new topic: Dash DataTable - Conditional Formatting


#59

A post was split to a new topic: Dash DataTable - Distinguishing between single row select and multi row select


#60

A post was split to a new topic: Dash DataTable - Controlling size


#61

Hi Chris,

I am facing the issue of Error loading layout". My code for app.layout is as follows:

app.layout = html.Div([
html.Div(dt.DataTable, style={‘display’: ‘none’}),
html.H4(‘Gapminder DataTable’),
dt.DataTable(
rows=DF_GAPMINDER.to_dict(‘records’),

    # optional - sets the order of columns
    columns=sorted(DF_GAPMINDER.columns),

    row_selectable=True,
    filterable=True,
    sortable=True,
    selected_row_indices=[],
    id='datatable-gapminder'
),
html.Div(id='selected-indexes'),
dcc.Graph(
    id='graph-gapminder'
),

], className=“container”)

any help is appreciated!!
image|551x500


#62

If you don’t mind sharing your code a bit ,how did you add the empty record dict to the rows property. I have trying to do this for hours now!

Thanks,
Sud