Many thanks!
Based on your idea, I have added some more lines that we can rename some other column names.
However, I think the data and column names of Table 1 aren’t actually changed due to the fact that this Table is always fed by the initial data (now I have changed to global data). I think we need a shared virtual table where its data will be pumped only once from the beginning and will be updated whatever we change data/column names in Table 1 or 2.
Ps: it’s mid night now, I’ll check it tomorrow.
from dash import Input, Output, State, Dash, dash_table, html, no_update, ctx
import pandas as pd
app = Dash(__name__)
# Example of a dataset below
global_df = pd.DataFrame({'A': [1, 2, 3, 12, 29],
'B': [4, 5, 6, 13, 21],
'C': [7, 8, 9, 14, 23],
'D': [4, 3, 1, 11, 13],
})
# The columns and data below are used for Table 1
global_columns = [
{"name": col, "id": col, "deletable": True, "renamable": True}
for col in global_df.columns
]
data = global_df.to_dict('records')
# data, cols for table 2
table1_cols = [col["name"] for col in global_columns]
data_table2 = [
{"sequence": i + 1,
"column_names": col_name}
for i, col_name in enumerate(table1_cols[0:])
]
columns_table2 = [
{"name": "Sequence", "id": "sequence"},
{"name": "Name", "id": "column_names"}
]
app.layout = html.Div(
style={"width": "400px", "height": "300px"},
children=[
html.H3('Table 1'),
dash_table.DataTable(
id='table_1',
editable=True,
columns=global_columns,
data=data,
row_deletable=True,
column_selectable="multi",
selected_columns=[],
style_cell={'textAlign': 'center'},
),
html.Hr(),
html.H3('Table 2'),
dash_table.DataTable(
id="table_2",
data=data_table2,
columns=columns_table2,
selected_cells=[],
editable=True,
row_selectable="multi",
selected_rows=[],
),
]
)
# A callback function to list column names of Table 1 in Table 2
@app.callback(
Output("table_2", "columns"),
Output("table_2", "data"),
Output("table_1", "columns"),
Output("table_1", "data"),
Input("table_1", "columns"),
Input("table_2", "data"),
Input("table_1", "data"),
)
def update_table2(table1_columns, table2_data, table1_data):
table_modified = ctx.triggered_id
if table_modified == "table_1":
table1_col_names = [col["name"] for col in table1_columns]
data_for_table2 = [
{"sequence": i + 1,
"column_names": col_name}
for i, col_name in enumerate(table1_col_names[0:])
]
columns_for_table2 = [
{"name": "Sequence", "id": "sequence"},
{"name": "Name", "id": "column_names"}
]
return columns_for_table2, data_for_table2, no_update, no_update
elif table_modified == "table_2":
table2_col_names = [d['column_names'] for d in table2_data]
# print(table2_col_names)
columns_for_table1 = [
{"name": col, "id": col, "deletable": True, "renamable": True}
for col in table2_col_names
]
# print(columns_for_table1)
# write code here
# we need to figure out how to take the data modified in table 2 and
# update the column names of table1 as well as its data
df_table1_data = pd.DataFrame(table1_data) # Convert the data of table 1 back to DataFrame
table1_old_names = df_table1_data.columns # Get column names of table1 data
total_length = len(table1_old_names)
# print("New Name: ", "'" + columns_for_table1[0]['name'] + "'")
# print("Old Name: ", "'" + table1_old_names[0] + "'")
# print("length: ", total_length)
print("Before:", df_table1_data.head())
for i in range(total_length):
new_name = "'" + columns_for_table1[i]['name'] + "'"
old_name = "'" + table1_old_names[i] + "'"
df_table1_data.rename(columns={old_name: new_name}, inplace=True)
print("After:", df_table1_data.head())
return no_update, no_update, columns_for_table1, df_table1_data.to_dict('records')
else:
return no_update
if __name__ == "__main__":
app.run_server(debug=True)