Editable Dash Table is not Working

Dear all,

I have a datatable reading the data from the dcc.Store. I want it to be editable such that I can modify the data manually. However, the editing feature is not working.

The code is shown below.

@app.callback(
    Output('raw-data-div', 'children'),
    [Input('stock-data', 'modified_timestamp'),
    Input('data-start', 'n_intervals')],
    State('stock-data', 'data'),
)
def gen_data_table(stock_data_timestamp, data_start_n_intervals, stock_data):

    if stock_data_timestamp != -1 or data_start_n_intervals is not None:

        div_children = []

        stock_data = jsonpickle.decode(stock_data)

        for symbol, stock in stock_data.items():

            df_current_and_others = stock.raw_data['current_and_others']
            df_quarterly = stock.raw_data['quarterly']
            df_annual = stock.raw_data['annual']

            div_children.extend(
                [
                    html.P(id='hihi'),
                    html.H3(f'{symbol}'),
                    html.H4('Current and others'),
                    dash_table.DataTable(
                        id=f'hihi_{symbol}',
                        data=df_current_and_others.to_dict('records'),
                        editable=True,
                        persistence=True,
                    ),
                    html.H4('Quarterly'),
                    dash_table.DataTable(
                        data=df_quarterly.to_dict('records'),
                        editable=True,
                        persistence=True,
                    ),
                    html.H4('Annual'),
                    dash_table.DataTable(
                        data=df_annual.to_dict('records'),
                        editable=True,
                        persistence=True,
                    ),
                    html.Hr(),
                ]
            )
        return div_children
    else:
        return dash.no_update

Please help me. Thank you.

I have tried adding an arbitrary callback function for the dashtable but it still did not work.

Anyone, please?

@lester1027
Iā€™d like to help, but Iā€™m not sure I understand your question. if you created a complete minimal example with some sample data that reproduces the issue, it will be easier for someone to give some feedback.

@AnnMarieW Thank you. The minimal example is provided below.

Apart from dash, pandas and jsonpickle are used to deal with the data.

The structure of the repository is like this.

repository
ā”œā”€ā”€ vis_components
ā”‚ ā”œā”€ā”€ data_tab.py
ā”‚ ā””ā”€ā”€ visualization_tab.py
ā”œā”€ā”€ dashboard_app.py
ā””ā”€ā”€ main_dash.py

dashboard_app.py

from dash import Dash, dcc, html
from dash.dependencies import Input, Output, State
from vis_components import visualization_tab, data_tab

from main_dash import app

app.layout = html.Div(
    children=[
        dcc.Interval(id='app-start', interval=1, max_intervals=1),
        dcc.Store(id='stock-symbol-all', storage_type='local'),
        dcc.Store(id='stock-symbol-selected', storage_type='local'),
        dcc.Store(id='stock-data', storage_type='local'),
        dcc.Tabs(id='tabs-bar', value='tab-visualization', persistence=True, children=[
            dcc.Tab(label='Visualization', value='tab-visualization'),
            dcc.Tab(label='Data', value='tab-data'),
        ]),
        html.Div(id='tabs-content')
    ]
)

# choose different tabs
@app.callback(
    Output('tabs-content', 'children'),
    Input('tabs-bar', 'value'),
)
def render_content(tab):
    if tab == 'tab-visualization':
        return visualization_tab.tab_visualization_layout
    elif tab == 'tab-data':
        return data_tab.tab_data_layout

if __name__ == '__main__':
    app.run_server(debug=True)

main_dash.py

from dash import Dash

app = Dash(__name__)
app.config.suppress_callback_exceptions = True

visualization_tab.py

import dash
from dash import Dash, dcc, html
from dash.dependencies import Input, Output, State
import plotly.graph_objects as go
import pandas as pd
import jsonpickle
import jsonpickle.ext.pandas as jsonpickle_pandas
jsonpickle_pandas.register_handlers()

from main_dash import app

tab_visualization_layout = html.Div([
    html.Button('Refresh data', id='refresh-data', n_clicks=0),
])


# get the stock data according to the stock names chosen
@app.callback(
    Output('stock-data', 'data'),
    Input('refresh-data', 'n_clicks'),
)
def get_stock_data(refresh_data,):
    if refresh_data >= 1:

        stock_data = {}

        stock_data['foo'] = pd.DataFrame(
            [
                {
                    'aaa': 213,
                    'bbb': 123,
                },
                {
                    'aaa': 65,
                    'bbb': 153,
                },
            ]
        )

        stock_data['bar'] = pd.DataFrame(
            [
                {
                    'aaa': 77,
                    'bbb': 153,
                },
                {
                    'aaa': 99,
                    'bbb': 73,
                },
            ]
        )

        stock_data = jsonpickle.encode(stock_data)

        return stock_data

    else:
        return dash.no_update

data_tab.py

import dash
from dash import Dash, dcc, html, dash_table
from dash.dependencies import Input, Output, State
import pandas as pd
import jsonpickle

from main_dash import app

tab_data_layout = html.Div(
    children=[
        html.P(id='trial'),
        dcc.Interval(id='data-start', interval=1, max_intervals=1),
        html.H2('Raw Data'),
        html.Hr(),
        html.Div(
            id='raw-data-div',
        )
    ]
)

@app.callback(
    Output('raw-data-div', 'children'),
    [Input('stock-data', 'modified_timestamp'),
    Input('data-start', 'n_intervals')],
    State('stock-data', 'data'),
)
def gen_data_table(stock_data_timestamp, data_start_n_intervals, stock_data):

    if stock_data_timestamp != -1 or data_start_n_intervals is not None:

        div_children = []

        stock_data = jsonpickle.decode(stock_data)

        for symbol, stock in stock_data.items():
            df = stock

            div_children.extend(
                [
                    html.H3(f'{symbol}'),
                    dash_table.DataTable(
                        id=f'hihi',
                        data=df.to_dict('records'),
                        editable=True,
                        persistence=True,
                    ),
                    html.Hr(),
                ]
            )
        return div_children
    else:
        return dash.no_update



@lester1027 Try defining the columns in the DataTable as well:

data=df.to_dict('records'),
columns=[{"name": i, "id": i} for i in df.columns],
1 Like

@AnnMarieW Thank you very much. It works.

1 Like