I have a simple dataframe:
import pandas as pd
df = pd.DataFrame({'Class1': [1, 2, 3, 4, 5],
'Class2': [6, 7, 8, 9, 10]}
)
I have created a data extraction function that splits the data based on the position of the column.
data_extraction.py
def dataExtraction(arg1):
df = pd.DataFrame({'Class1': [1, 2, 3, 4, 5],
'Class2': [6, 7, 8, 9, 10]}) ## <-- or Import df from somewhere
df = df[[f'Class{arg1}']]
return df
layout.py
import dash_bootstrap_components as dbc
from dash import dcc, html, Input, Output, callback
from dash import Dash, dash_table, State
import dash_daq as daq
import pandas as pd
def update_page(arg1, arg2):
layout = html.Div(children=[
html.H1(f'Class {arg1}'),
daq.NumericInput(
id='numericinput1',
min=0,
max=100,
value=0, ),
html.Br(),
dash_table.DataTable(
id='tableTest',
data=arg2.to_dict('records'),
columns=[{"name": i, "id": i} for i in arg2.columns]),
])
return layout
@callback(
Output('tableTest', 'data'),
Input('numericinput1', 'value'),
State('tableTest', 'data'),
)
def updateTableTest(x,data):
data = pd.DataFrame(data)
if x > 0:
**print(data) # Indicator that shows callback is working**
print("CALLBACK WORKING!!!")
return data.to_dict('records')
return data.to_dict('records')
I have also constructed a tab page as follows that consists of a page with 2 tabs. The tab_page displays the tabs with their respective data column (E.g. tab 1 for column 1). I have written 'print (data)' to check that the callback in the layout function is working. It is working for one tab but not the other.
tab_page.py
import layout as lay
import data_extraction as de
import dash_bootstrap_components as dbc
from dash import html, Dash
import dash
app = Dash()
dash.register_page(__name__,
path='/tabs')
def get_layout(position):
df = de.dataExtraction(position)
layout = lay.update_page(position, df)
return layout
tab1_content = dbc.Card(
dbc.CardBody(
[
**get_layout(1)#<--- CALLBACK NOT WORKING HERE The print(data) is NOT working**
]
),
className="mt-1",
)
tab2_content = dbc.Card(
dbc.CardBody(
[
get_layout(2) #<--- The print(data) is working
]
),
className="mt-2",
)
layout = html.Div(children = [
dbc.Tabs(
[
dbc.Tab(tab1_content, label="1",activeLabelClassName="text-success"),
dbc.Tab(tab2_content, label="2",activeLabelClassName="text-success"),
]
)])
app.layout = [layout]
if __name__ == '__main__':
app.run(debug=True)
The callback in the layout works for the get_layout(2) but not get_layout(1). Why does it work for one and not the other?
The problem that you have duplicated ids in the layout. And single callback can't be linked to two objects with the same ids:
Fix 1 - remove duplicated ids
# layout.py
def update_page(arg1, arg2):
layout = html.Div(children=[
html.H1(f'Class {arg1}'),
daq.NumericInput(
id=f"numericinput{arg1}",
min=0,
max=100,
value=0, ),
html.Br(),
dash_table.DataTable(
id=f"tableTest{arg1}",
data=arg2.to_dict('records'),
columns=[{"name": i, "id": i} for i in arg2.columns]),
])
return layout
Fix 2 - make two callbacks, one for each table
# layout.py
def create_callback(i):
@callback(
Output(f'tableTest{i}', 'data'),
Input(f'numericinput{i}', 'value'),
State(f'tableTest{i}', 'data'),
)
def updateTableTest(x, data):
data = pd.DataFrame(data)
print(x)
if x > 0:
print(data) # Indicator that shows callback is working
return data.to_dict('records')
return data.to_dict('records')
return updateTableTest
Fix 3 - initiate callbacks
# tab_page.py
...
# initiate callbacks:
app.layout = [layout]
lay.create_callback(1)
lay.create_callback(2)
if __name__ == '__main__':
app.run(debug=True)
...