tristan
tristan

Reputation: 135

How to replace a Dash/Plotly Table after it received new Data / or update the current Table

i want to build a DataTable which gets updated from time to time. Each time this happens, the table is supposed to fetch the data from a csv file. In order to do this i build a function that generates and returns the table. This works, after the second update - but the first table i generated stays and therefore i end up with to tables where one does what i want but the other one just stays...:

The one on top is the second one, which updates. The one in the bottom is the on i generated first,

This is my code:

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

import dash_html_components as html
import pandas as pd


df = pd.read_csv('.../dummy2_csv.csv')


def maketable(dataf):
    tab = html.Div([dash_table.DataTable(
                id='adding-rows-table',
                editable=True,
                data=dataf.to_dict('rows'),
                columns=[{'name': i, 'id': i} for i in dataf.columns])])
    return tab


app = dash.Dash(__name__)


app.layout = html.Div([
    html.Div(id='my-div'),
    maketable(df),
    html.Button('+', id='editing-rows-button', n_clicks=0),
    html.Button('update', id='btn-save', n_clicks=0)
])



@app.callback(
    Output(component_id='my-div', component_property='children'),
    [Input('btn-save', 'n_clicks'), Input('adding-rows-table', 'data')]
)
def update_output_div(n_clicks, data):
    changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]
    if 'btn-save' in changed_id:
        df2 = pd.DataFrame(data)

        for col in df2.columns:
            # new values
            df2[col].values[:] = random.randint(0,9)
        df2.to_csv('.../dummy2_csv.csv', encoding='utf-8', index=False)
        return maketable(df2)


@app.callback(
    Output('adding-rows-table', 'data'),
    [Input('editing-rows-button', 'n_clicks')],
    [State('adding-rows-table', 'data'),
     State('adding-rows-table', 'columns')])
def add_row(n_clicks, rows, columns):
    if n_clicks > 0:
        rows.append({c['id']: '' for c in columns})
    return rows


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

Thanks in advance for your help!

best, t.

Upvotes: 1

Views: 3811

Answers (2)

tristan
tristan

Reputation: 135

I got it to work

  • the issue, was in callback function.

check:

import dash
from dash.dependencies import Input, Output, State
import dash_table
import dash_daq as daq
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd


df = pd.read_csv('.../dummy2_csv.csv')

body = dbc.Container(
    [
        dbc.Row(
            [
                dash_table.DataTable(id="dash_neu", editable=True, row_deletable=True, columns=[{'name': i, 'id': i} for i in df.columns], data=df.to_dict('records')),
                dbc.Col(html.Button('+', id='editing-rows-button', n_clicks=0)),
                dbc.Col(html.Button('update', id='btn-save', n_clicks=0))
            ]
        )])

app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = html.Div([body])


@app.callback(
    [dash.dependencies.Output("dash_neu", "data"), dash.dependencies.Output("dash_neu", "columns")],
    [Input("btn-save", "n_clicks"), Input('editing-rows-button', 'n_clicks')],
    [State('dash_neu', 'data'), State('dash_neu', 'columns')]
)
def update(button, clicked, data, columns):
    changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]
    if 'btn-save' in changed_id:
        df = pd.DataFrame(data)
        df.to_csv('.../dummy2_csv.csv', encoding='utf-8', index=False)
        columns = [{'name': i, 'id': i} for i in df.columns]
        data = df.to_dict('records')
        return data, columns
    if 'editing-rows-button' in changed_id:
        if clicked > 0:
             data.append({c['id']: '' for c in columns})
        return data, columns
    return data, columns

Upvotes: 2

coralvanda
coralvanda

Reputation: 6596

It looks like the problem is because you've called the function to build the table outside of the div which receives the table from your callback. Try changing your layout to this:

app.layout = html.Div([
    html.Div(id='my-div', children=[maketable(df)]),
    html.Button('+', id='editing-rows-button', n_clicks=0),
    html.Button('update', id='btn-save', n_clicks=0)
])

Upvotes: 0

Related Questions