Reputation: 135
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
Reputation: 135
I got it to work
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
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