[Solved] Updating a Dash Datatable rows with row_update and rows

I have a table of stock tickers in a dash datatable with stock performance metrics. The last row is a custom etf that weights the returns and averages them together.
i.e.


What I’m trying to do is update the custom etf columns after everything has been reweighted. Everything is preset to be equally weighted.

@app.callback(
dash.dependencies.Output(‘comps-table’,‘rows’),
[ dash.dependencies.Input(‘comps-table’, ‘row_update’),
dash.dependencies.Input(‘comps-table’, ‘rows’),
])
def update_graph(tickers, selected_ticker, row_update, rows):
if row_update is not None:
creates reweighted etf
return rows

Is there a way to do this? I already have it set up so when you change the weighting it effects a graph which works great but i would like the table to update as well.

Thanks

2 Likes

Great question @partybearlj

Here’s a simple that updates the 2nd column based off of edits in the first column:

import copy
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 json
import pandas as pd
import plotly

app = dash.Dash()

app.scripts.config.serve_locally = True

RECORDS = [
    {'Input': '', 'Output': ''}
    for i in range(100)
]

app.layout = html.Div([
    html.H4('Editable DataTable'),
    html.Div([
        html.Div(
            children=dt.DataTable(
                rows=RECORDS,

                # optional - sets the order of columns
                columns=['Input', 'Output'],

                editable=True,

                id='editable-table'
            ),
            className='six columns'
        ),
        html.Pre(id='output', className='six columns')
    ])
], className='container')


@app.callback(
    Output('output', 'children'),
    [Input('editable-table', 'row_update'),
     Input('editable-table', 'rows')])
def display_output(row_update, rows):
    return html.Div(className='row', children=[
        html.Div([
            html.Code('row_update'),
            html.Pre(json.dumps(row_update, indent=2))
        ], className='six columns'),
        html.Div([
            html.Code('rows'),
            html.Pre(json.dumps(rows, indent=2))
        ], className='six columns'),
    ])


@app.callback(
    Output('editable-table', 'rows'),
    [Input('editable-table', 'row_update')],
    [State('editable-table', 'rows')])
def update_rows(row_update, rows):
    row_copy = copy.deepcopy(rows)
    if row_update:
        updated_row_index = row_update[0]['from_row']
        updated_value = row_update[0]['updated'].values()[0]
        row_copy[updated_row_index]['Output'] = (
            float(updated_value) ** 2
        )
    return row_copy


app.css.append_css({
    "external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"
})

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

dash-datatable-editable-update-self

2 Likes

Hey thanks a lot this is exactly what I needed!

Has datatable been updated so this syntax is no longer usable?

I used ‘active_cell’ with ‘data_timestamp’. I also used that to make a call back to update a database table.

import time
import pandas as pd
import dash_table
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html


app = dash.Dash()
app.config.suppress_callback_exceptions = False
app.scripts.config.serve_locally = True
app.css.config.serve_locally = True

df = pd.DataFrame([[1, 2], [3, 4], [5, 6], [7, 8]], columns=["A", "B"])
           
app.layout = html.Div([
    html.H1(
        children='Sample Table - Shows how to identify modified Row',
        style={
            'textAlign': 'center'
        }
    ),

                   
    dash_table.DataTable(
                id='table-editing-simple',
                columns=[
                    {"name": "A", "id": "A", "editable": False},
                    {"name": "B", "id": "B", "editable": True}],
                data = df.to_dict("rows"),
                editable = True
                ),
    html.Div(
            html.H5(
                id='table-action-outputs',
                children='',
                style={'textAlign': 'left'}),
            style={'width': '100%', 'display': 'inline-block', 'float': 'left'},
            ),

])



@app.callback(Output('table-action-outputs', 'children'),
              [Input('table-editing-simple', 'data_timestamp'),
              Input('table-editing-simple', 'active_cell'),
              Input('table-editing-simple', 'data')])
def update_database(time_updated, cell_coordinates, table_data):
    time_updated = round(time_updated / 1000)
    time_now = round(time.time()) - 2
    if (time_updated) >= time_now:
       db_response = str(time_updated) + " " +  str(time_now)
       str_return = "Data timestamp:" + str(time_updated) 
       str_return2 = ".  Did you update this row? " + str(table_data[cell_coordinates[0]])
       sql_query = "UPDATE table SET B = '{table_data[cell_coordinates[0]][cell_coordinates[1]]}', MODIFIED_DATE = {time_updated} WHERE A = '{table_data[cell_coordinates[0]][cell_coordinates[0]]}'"
       db_response = f".  Sample DB SQL Update statement: {sql_query}"  
    else:
       time_round = round(time.time())
       str_return = "No time match. " + str(type(time_updated)) + " is the Dash updated time which does not match this server time:  " + str(time_round) + "\n"
       str_return2 = ".  No matching record found due to time issue.\n"
       db_response = ".  No DB update due to time gap issue.\n"
    return str_return, str_return2, db_response

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

2 Likes

I like the approach, however, this doesn’t seem to work either? As soon as you edit a cell and press Enter, the active_cell is no longer the previously edited cell.

Apparently, there is no way around to compare data_previous and data?

1 Like

How do I make this a working one. I am not getting the table in the left, just the right (with row_update and rows). Thank you!

what is the significance of this code chunk

Shouldnt the second app.callback display the updated value in the output column?
Pardon if the question is noob, i m new to dash plotly.

It isn’t clear to me either. Replacing the function display_output in the original code at the top with chriddyp’s does not work: the original table does not display and is not editable.
Replacing

import dash_table_experiments as dt

with

import dash_table as dt

also does not work. This looks like exactly the problem I have been having the past ~week. Hoping someone can help me!

Cheers,

Carl

Hi @chriddyp please can you post an implementation for a datatble with dropdown inputs where if i select a particular value from two columns it gives an ouput in another column emphacies is on dropdown in datatable facing this challenge for a month now