Open
Description
Environment
-
Python 3.10.7
-
pip list | grep dash
dash 2.7.0 dash-core-components 2.0.0 dash-html-components 2.0.0 dash-table 5.0.0
-
same on all browsers I tested:
- on MacOS 12.6:
- Chrome 107.0.5304.110
- Version 16.0 (17614.1.25.9.10, 17614)
- Firefox 105.0.3 (64-bit)
- on Windows 10 Pro
- Microsoft Edge 107.0.1418.52 (Official build) (64-bit)
- on MacOS 12.6:
Describe the bug
When doing a paste action (as in copy&paste), two things happen:
data
property gets updated- ☝️ this is as expected
data_previous
property takes on the pasted value- ☝️ this seems to be a bug
Expected behavior
After a paste, I expect data_previous
property to contain last the data before the paste.
Why is this Important
Normally, comparing data
with data_previous
makes it is easy to see what has changed. This is important when values in different columns are inter-dependent. This bug makes it impossible (without non-pretty workarounds) to tell which values were pasted into the table.
Screen Recording
DataTable.bug.on.paste.mp4
Example App
import dash
import pandas as pd
from dash import dash_table, dcc, html, Output, Input, State
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/solar.csv')
app = dash.Dash(__name__)
app.layout = html.Div([
dash_table.DataTable(
id='table',
columns=[{"name": i, "id": i, "editable": True} for i in df.columns],
data=df.to_dict('records'),
editable=True,
),
# counter for callback calls, to make sure the callback is not running multiple times:
html.H4("Callback count:"),
dcc.Input(id="count", value=0),
# current and old data for inspection:
html.H4("Current data:"),
html.Pre(id="data", children=""),
html.H4("Previous data:"),
html.Pre(id="prev_data", children=""),
])
@app.callback(
Output("data", "children"),
Output("prev_data", "children"),
Output("count", "value"),
Input("table", "data"),
State("table", "data_previous"),
State("count", "value"),
)
def show_data_and_prev_data(data, prev_data, count):
return str(pd.DataFrame(data)), str(pd.DataFrame(prev_data)), int(count) + 1
if __name__ == '__main__':
app.run_server(debug=True)