# Update a dash datatable with callbacks

**URL:** <https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382>\
**Category:** Dash Python\
**Created:** [March 26, 2019, 3:03am UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382 "2019-03-26T03:03:57Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![jelkhoury](https://avatars.discourse-cdn.com/v4/letter/j/9de0a6/32.png) [@jelkhoury](https://community.plotly.com/u/jelkhoury)\
**Post date:** [March 26, 2019, 3:03am UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/1 "2019-03-26T03:03:57Z")

</div>

Hi everyone,

I have a data-table which I have to include in my layout as I need to use it as Input for one of my callbacks

I also want to update this table with another callback.  
This works fine if I update the data

But since with the new release we can format the columns I would like to update the columns too as I round some numbers depending on the data itself

If I create a callback with multiple outputs (data and columns) this fails  
it seems that the only way is to separate the callbacks in this case one for data and one for columns

Is this an intended behavior? If so why?  
Or is it an identified bug which will be fixed in a next release?

---

<div class="post-metadata">

**Author:** ![Marc-Andre](https://avatars.discourse-cdn.com/v4/letter/m/e19b73/32.png) [@Marc-Andre](https://community.plotly.com/u/Marc-Andre)\
**Post date:** [March 26, 2019, 1:33pm UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/2 "2019-03-26T13:33:06Z")

</div>

> [@jelkhoury](#):
>
> If I create a callback with multiple outputs (data and columns) this fails  
> it seems that the only way is to separate the callbacks in this case one for data and one for columns

It should be possible to output both the `data` and the `columns` in a single callback.

Here’s a working, if crude example:

```auto
# -*- coding: utf-8 -*-
import dash
import dash_html_components as html

from dash.dependencies import Input, Output, State
from dash_table import DataTable

import pandas as pd

url = "https://github.com/plotly/datasets/raw/master/" "26k-consumer-complaints.csv"
df = pd.read_csv(url)

app = dash.Dash( __name__ )
app.scripts.config.serve_locally = True

columns = [
    {"id": 0, "name": "Complaint ID"},
    {"id": 1, "name": "Product"},
    {"id": 2, "name": "Sub-product"},
    {"id": 3, "name": "Issue"},
    {"id": 4, "name": "Sub-issue"},
    {"id": 5, "name": "State"},
    {"id": 6, "name": "ZIP"},
    {"id": 7, "name": "code"},
    {"id": 8, "name": "Date received"},
    {"id": 9, "name": "Date sent to company"},
    {"id": 10, "name": "Company"},
    {"id": 11, "name": "Company response"},
    {"id": 12, "name": "Timely response?"},
    {"id": 13, "name": "Consumer disputed?"},
]

app.layout = html.Div([
    html.Button(
        ['Update'],
        id='btn'
    ),
    DataTable(
        id='table',
        data=[]
    )
])

@app.callback(
    [Output("table", "data"), Output('table', 'columns')],
    [Input("btn", "n_clicks")]
)
def updateTable(n_clicks):
    if n_clicks is None:
        return df.values[0:100], columns

    return df.values[100:110], columns[0:3]

if __name__ == " __main__":
    app.run_server(port=8053)

```

If still experiencing issues, can you provide a simple example of the problematic behavior you’re experiencing?

Thanks!

---

<div class="post-metadata">

**Author:** ![jelkhoury](https://avatars.discourse-cdn.com/v4/letter/j/9de0a6/32.png) [@jelkhoury](https://community.plotly.com/u/jelkhoury)\
**Post date:** [March 27, 2019, 4:47am UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/3 "2019-03-27T04:47:14Z")

</div>

Thank you Marc-Andre

I worked on creating a code snippet to illustrate the problem I see without any dependencies:

version 1 works I am updating only the data

version 2 I am updating the data and the columns and the table is empty as no columns are showing:

for version 2 please do comment back in the 2nd Output and return of the callback function

Thanks

This is the code :

```
import dash
import dash_core_components as dcc 
import dash_html_components as html 
import dash_table 
from dash_table.Format import Format, Scheme, Sign, Symbol
import dash_table.FormatTemplate as FormatTemplate
from dash.dependencies import Input, Output, State
import pandas as pd
import numpy as np

app = dash.Dash( __name__ )
       
app.title = 'Futures'

app.layout = html.Div(style={'marginLeft':25,'marginRight':25},
                    children=[ 
                        html.Div(className='row',children=[
                                        html.Div(className='four columns',
                                        children =[
                                        ]),
                                html.Div(className='four columns',
                                    children =[
                                                html.H6('Order Book'),
                                                html.Hr(style={'border-color':'#cb1828'}),
                                                html.Div(children=[dash_table.DataTable(id='fut-order-table',
                                                columns=[{'id':'from_mid','name':'From Mid','type':'numeric','format':FormatTemplate.percentage(4)},
                                                {'id':'price','name':'Price'},{'id':'size','name':'Size'},{'id':'cum_size','name': 'Size Total'},
                                                {'id':'size_$','name':'Size $','type':'numeric','format':FormatTemplate.money(0)},
                                                {'id':'cum_size_$','name':'Size Total $','type':'numeric','format':FormatTemplate.money(0)},
                                                {'id':'average_fill','name':'Averge Fill'},{'id':'exc','name':'Exchange'},
                                                {'id':'side','name':'side','hidden':True}],
                                                    style_table={'border': 'thin lightgrey solid'},
                                                    style_header={'backgroundColor':'lightgrey','fontWeight':'bold'},
                                                    style_cell={'textAlign':'center','width':'12%'},
                                                    style_data_conditional=[{
                                                        'if' : {'filter': 'side eq "bid"' },
                                                        'color':'blue'
                                                                }
                                                        ]+[
                                                        {
                                                        'if' : {'filter': 'side eq "ask"' },
                                                        'color':'rgb(203,24,40)'
                                                    }]+[
                                                        { 'if': {'row_index':'odd'},
                                                        'backgroundColor':'rgb(242,242,242)'}
                                                    ]+[
                                                        {'if':{'column_id':'price'},
                                                        'fontWeight':'bold',
                                                        'border': 'thin lightgrey solid'}
                                                    ]+[{'if':{'column_id':'from_mid'},
                                                        'fontWeight':'bold'}
                                                    ],
                                                    style_as_list_view=True
                                                )
                                                ]),
                                                html.Hr(style={'border-color':'#cb1828'}),
                                                html.H6('Liquidity Metrics'),
                                                html.P(id='fut-liquidity-table'),
                                                html.H6('Slippage %'),
                                                html.P(id='fut-depth-table'),
                                                html.H6('Coin Stats'),
                                                html.P(id='fut-stat-table')
                                        ]),

                                html.Div(className='four columns',
                                    children =[html.H6('Order Management'),
                                    html.Hr(style={'border-color':'#cb1828'}),
                                    html.H6('Orders'),
                                    html.Hr(style={'border-color':'#cb1828'}),
                                    html.Div(children = [
                                        html.Button(id='update_click',children =['Refresh'],
                                        style = {'margin-top' :'10px','background-color':'#cb1828','color':'#FFF'})]),
                            
                                    ])     
                        ]),
                    ])
@app.callback(
            Output('fut-order-table','data'),#, Output('fut-order-table','columns')],
            [Input('update_click','n_clicks')],)

def update_page(n_clicks):
    step = .0001
    # order table columns
    r = int(np.ceil(-np.log(step)/np.log(10)))-2
    columns_ob=[{'id':'from_mid','name':'From Mid','type':'numeric','format':FormatTemplate.percentage(r)},
                {'id':'price','name':'Price'},{'id':'size','name':'Size'},{'id':'cum_size','name': 'Size Total'},
                {'id':'size_$','name':'Size $','type':'numeric','format':FormatTemplate.money(0)},
                {'id':'cum_size_$','name':'Size Total $','type':'numeric','format':FormatTemplate.money(0)},
                {'id':'average_fill','name':'Averge Fill'},{'id':'exc','name':'Ex'},
                {'id':'side','name':'side','hidden':True}],
    # order table data
    df = pd.DataFrame(np.random.randn(24,9),columns=['from_mid','price','size','cum_size','size_$','cum_size_$','average_fill','exc','side'])
    data_ob = df.to_dict('rows')
    return (data_ob)#,columns_ob) 

if __name__ == ' __main__' :
    app.run_server(port=8055,debug=True)
```

---

<div class="post-metadata">

**Author:** ![jelkhoury](https://avatars.discourse-cdn.com/v4/letter/j/9de0a6/32.png) [@jelkhoury](https://community.plotly.com/u/jelkhoury)\
**Post date:** [March 27, 2019, 5:34am UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/4 "2019-03-27T05:34:10Z")

</div>

I suspect this related to the FormatTemplate objects being not Json

---

<div class="post-metadata">

**Author:** ![dhenke](https://avatars.discourse-cdn.com/v4/letter/d/58956e/32.png) [@dhenke](https://community.plotly.com/u/dhenke)\
**Post date:** [April 10, 2019, 1:43pm UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/5 "2019-04-10T13:43:49Z")

</div>

Any solution for this one already?

---

<div class="post-metadata">

**Author:** ![lahashh](https://avatars.discourse-cdn.com/v4/letter/l/3be4f8/32.png) [@lahashh](https://community.plotly.com/u/lahashh)\
**Post date:** [April 10, 2019, 1:58pm UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/6 "2019-04-10T13:58:54Z")

</div>

If the problem is the datatable why not just storing your data in another hidden div? This way you don’t have to deal with the table itself but just a json stored in an html component, update it via first callback and let this div be the input that fires callbacks for other components in your page [https://dash.plot.ly/sharing-data-between-callbacks](https://dash.plot.ly/sharing-data-between-callbacks).

---

<div class="post-metadata">

**Author:** ![jelkhoury](https://avatars.discourse-cdn.com/v4/letter/j/9de0a6/32.png) [@jelkhoury](https://community.plotly.com/u/jelkhoury)\
**Post date:** [May 10, 2019, 10:43am UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/8 "2019-05-10T10:43:56Z")

</div>

@Marc-Andre  
This totally works

the problem was a coma at the end of my columns definition  
columns = [{},{},{}] **,**  
which had made my columns variable a tuple instead of a list  
so columns are updatable by callbacks including FormatingTemplate

The new debuging tool of Dash == 0.43.0 made this solution possible  
Thanks

---

<div class="post-metadata">

**Author:** ![vaclavku](https://avatars.discourse-cdn.com/v4/letter/v/8c91f0/32.png) [@vaclavku](https://community.plotly.com/u/vaclavku)\
**Post date:** [May 15, 2019, 4:56pm UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/9 "2019-05-15T16:56:01Z")

</div>

Hello Marc-Andre,  
it seems to me that I’ve similar problem like mentioned here.  
I try to update the table in general by the value selected in the dropdown.  
In the layout, I define the table in this way:  
html.Div(dtab.DataTable  
(id = ‘exch\_table’,  
data=[]  
),

The call back is like:  
@app.callback([Output(‘exch\_table’, ‘data’), Output(‘exch\_table’, ‘columns’)],  
[Input(‘exch\_dropdown’, ‘value’)])

def update\_table(selected\_value):  
df = pd.read\_sql(selected\_value, conn)  
columns=[{“name”: i, “id”: i} for i in df.columns],  
data=df.to\_dict(‘records’)  
return data, columns

However, the outputs are no dash.Output.

Any feedback is very appreciated.  
Kind regards,  
Vaclav

---

<div class="post-metadata">

**Author:** ![vaclavku](https://avatars.discourse-cdn.com/v4/letter/v/8c91f0/32.png) [@vaclavku](https://community.plotly.com/u/vaclavku)\
**Post date:** [May 16, 2019, 7:32am UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/10 "2019-05-16T07:32:32Z")

</div>

Hi, this is my solution:  
as the Das h v39 enables multiple out put (update is necessary) the layout is:  
html.Div(dtab.DataTable(id = ‘exch\_table’)

The call back is:  
def update\_table(selected\_value):  
df = pd.read\_sql(selected\_value, conn)  
columns=[{“name”: i, “id”: i} for i in df.columns]  
data=df.to\_dict(‘records’)  
return columns, data

It should work. The dash datatable is being updated based on the new pandas dataframe.

Good luck.  
Vaclav

---

<div class="post-metadata">

**Author:** ![offtackle24](https://avatars.discourse-cdn.com/v4/letter/o/4491bb/32.png) [@offtackle24](https://community.plotly.com/u/offtackle24)\
**Post date:** [November 11, 2019, 4:15am UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/11 "2019-11-11T04:15:49Z")

</div>

edit nvm I figured out the problem myself.

---

<div class="post-metadata">

**Author:** ![kalt](https://avatars.discourse-cdn.com/v4/letter/k/b9e5f3/32.png) [@kalt](https://community.plotly.com/u/kalt)\
**Post date:** [May 28, 2020, 6:41am UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/12 "2020-05-28T06:41:05Z")

</div>

the example @Marc-Andre suggested works so far. However if I use debug=True I always get an error meassage. Does anyone know why?

---

<div class="post-metadata">

**Author:** ![chriddyp](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/chriddyp/32/16855_2.png) [@chriddyp](https://community.plotly.com/u/chriddyp)\
**Post date:** [May 28, 2020, 3:19pm UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/13 "2020-05-28T15:19:11Z")

</div>

> [@kalt](#):
>
> I always get an error meassage

what’s the error message?

---

<div class="post-metadata">

**Author:** ![kalt](https://avatars.discourse-cdn.com/v4/letter/k/b9e5f3/32.png) [@kalt](https://community.plotly.com/u/kalt)\
**Post date:** [May 29, 2020, 6:21am UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/14 "2020-05-29T06:21:31Z")

</div>

I should have send it in my first message. I always get the following error, but only with debug=True.

Invalid argument `columns[0].id` passed into DataTable with ID “table”.  
Expected `string`.

Failed component prop type: Invalid component prop `data[0]` of type `array` supplied to `function t(){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),y(this,m(t).apply(this,arguments))}`  
Was supplied type `number`.

---

<div class="post-metadata">

**Author:** ![kalt](https://avatars.discourse-cdn.com/v4/letter/k/b9e5f3/32.png) [@kalt](https://community.plotly.com/u/kalt)\
**Post date:** [June 18, 2020, 11:28am UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/15 "2020-06-18T11:28:48Z")

</div>

@chriddyp any idea what is the problem?

---

<div class="post-metadata">

**Author:** ![kozoria](https://avatars.discourse-cdn.com/v4/letter/k/3d9bf3/32.png) [@kozoria](https://community.plotly.com/u/kozoria)\
**Post date:** [July 1, 2020, 1:41am UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/16 "2020-07-01T01:41:07Z")

</div>

I have the same issue, but it only happens when I have debug=True and the table appears just fine. Here are other threads I found with the same issue but no solution quite yet.

> [@Invalid argument \`columns\[1\].name\` passed into DataTable](https://community.plotly.com/t/invalid-argument-columns-1-name-passed-into-datatable/25478/2):
>
> I had just ran into the same error, and for me the issue was that the column names were integers and not strings. so then the dictionary created in columns=[{'name': i, 'id': i,} for i in df.columns] gets an error because it will read {‘name’: 2013, ‘id’: ‘2013’} and not {‘name’: ‘2013’, ‘id’: ‘2013’}.

> [@Dash\_table with debug mode throws error](https://community.plotly.com/t/dash-table-with-debug-mode-throws-error/39496/3):
>
> Found another thread with similar issue.

---

<div class="post-metadata">

**Author:** ![nyck33](https://avatars.discourse-cdn.com/v4/letter/n/a8b319/32.png) [@nyck33](https://community.plotly.com/u/nyck33)\
**Post date:** [November 3, 2020, 6:54am UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/17 "2020-11-03T06:54:55Z")

</div>

@Marc-Andre

Does that example really work? I tried extending it and it won’t even hit a breakpoint in the callback on Pycharm debugger.

My layout for the tables:

```auto
DataTable(
        id="conversion-table",
        data=[],
        style_cell={'textAlign': 'left'},
        style_data_conditional=[{
            'if': {'row_index': 'odd'},
            'backgroundColor': 'rgb(248,248,248)'
        }],
        style_header={
            'backgroundColor': 'rgb(230,230,230)',
            'fontWeight': 'bold'
        },
    ),
    html.Div(
        html.H5("Nutrients")
    ),
    html.Br(),
    DataTable(
        id="nutrients-table",
        data=[],
        style_cell_conditional=[{
            'if': {'column_id': c},
            'textAlign': 'left'
        } for c in ['Name']
        ],
        style_data_conditional=[{
            'if': {'row_index': 'odd'},
            'backgroundColor': 'rgb(248,248,248)'
        }],
        style_header={
            'backgroundColor': 'rgb(230,230,230)',
            'fontWeight': 'bold'
        },
    ),

```

and my callback:

```auto
@app.callback(
        Output('table-foodgroup-source', 'children'),
        Output('conversion-table', 'data'),
        Output('conversions-table', 'columns'),
        Output('nutrients-table', 'data'),
        Output('nutrients-table', 'columns'),
        Input('search-ingredient', 'value')
    )
    def show_tables(ingredient):
        '''
        return top table, conversions table, nutrients table, yield table,
        refuse table
        '''
        food_id = food_to_id_dict[ingredient]
        food = CNFFoodName.objects.get(id=str(food_id))
        food_grp = food.food_group.name
        food_src = food.food_source.description
        food_sci_name = "n/a"
        if food.scientific_name:
            food_sci_name = food.scientific_name
        # table for food group, source, scientific name
        food_group_table = html.Table([
                                html.Thead([
                                    html.Tr([html.Th("Group"), html.Th("Source"), html.Th("Scientific Name")])
                                ]),
                                html.Tbody([
                                    html.Tr([
                                        html.Td(food_grp),html.Td(food_src),html.Td(food_sci_name)
                                    ])
                                ])
                            ])

        conversions_df = make_conversions_df(food_id)
        #conversions_cols = [{"id": i, "name": conversions_df.columns[i]} for i in range(len(conversions_df.columns))]
        conversions_cols = [{"name": i, "id": i} for i in conversions_df.columns]
        conversions_data = conversions_df.to_dict('records')

        nutrients_df = make_nutrients_df(food_id)
        #nutrients_cols = [{"id": i, "name": nutrients_df.columns[i]} for i in range(len(nutrients_df.columns))]
        nutrients_cols = [{"name": i, "id": i} for i in nutrients_df.columns]
        nutrients_data = nutrients_df.to_dict('records')
        #nutrients_table = make_nutrients_table(nutrients_df)

        return food_group_table, conversions_data, conversions_cols,\
               nutrients_data, nutrients_cols

```

---

<div class="post-metadata">

**Author:** ![frost](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/frost/32/2896_2.png) [@frost](https://community.plotly.com/u/frost)\
**Post date:** [April 8, 2021, 11:26am UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/18 "2021-04-08T11:26:38Z")

</div>

I have similar issue. I try to update data\_table from callback, returning columns and rows like:

```auto
@app.callback(
    Output('data_prev', 'columns'),
    Output('data_prev', 'data'),
    
    Input('btn_parse','n_clicks'),
    <...>
    , prevent_initial_call =True
)
def parse_base(n_clicks, ...)
	<...>

	cols = [{"name": i, "id": i} for i in prsr.data.columns]
	rows = prsr.data.head(20).to_dict('records')
	
	return cols, rows

```

But it ends up with an error:

```auto
The value in question is either the only value returned,
or is in the top level of the returned list,

and has string representation
`([{'name': 'process', 'id': 'process'}, {'name': 'Func', 'id': 'Func'}, {'name': 'res', 'id': 'res'}, {'name': 'txt', 'id': 'txt'}, {'name': 'time', 'id': 'time'}, {'name': 'duration', 'id': 'duration'}, {'name': 'event', 'id': 'event'}, {'name': 'level', 'id': 'level'}, {'name': 'src', 'id': 'src'}, {'name': 'raw_row', 'id': 'raw_row'}, {'name': 'Exception', 'id': 'Exception'}, {'name': 'Descr', 'id': 'Descr'}, {'name': 'ServerComputerName', 'id': 'ServerComputerName'}, {'name': 'Usr', 'id': 'Usr'}, {'name': 'OSThread', 'id': 'OSThread'}, {'name': 'p:processName', 'id': 'p:processName'}, {'name': 't:clientID', 'id': 't:clientID'}, {'name': 't:applicationName', 'id': 't:applicationName'}, {'name': 't:computerName', 'id': 't:computerName'}, {'name': 't:connectID', 'id': 't:connectID'}, {'name': 'SessionID', 'id': 'SessionID'}, {'name': 'Query', 'id': 'Query'}, {'name': 'Context', 'id': 'Context'}, {'name': 'DeadlockConnectionIntersections', 'id': 'DeadlockConnectionIntersections'}, {'name': 'dbpid', 'id': 'dbpid'}], 
[{'process': 'mon_info_plugin', 'Func': 'getLicense', 'res': <...skipped 15400 chars..> 'dbpid': <NA>}])`

In general, Dash properties can only be
dash components, strings, dictionaries, numbers, None,
or lists of those.

```

For some reason, my output really gets wrapped into tuple.

Changing Debug switch does not change anything.

Maybe I’m passing too many data?

---

<div class="post-metadata">

**Author:** ![frost](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/frost/32/2896_2.png) [@frost](https://community.plotly.com/u/frost)\
**Post date:** [April 8, 2021, 1:39pm UTC](https://community.plotly.com/t/update-a-dash-datatable-with-callbacks/21382/19 "2021-04-08T13:39:01Z")

</div>

Problem solved.

There were \< NA \> values inside ‘rows’. They confused Dash.

Had to ‘fillna’ before showing data
