I have created the following code to generate an output based on an dropdown which lies in a tab. However, the code is not working and produces the following error:
Attempting to connect a callback Input item to component: "my-input" but no components with that id exist in the layout.
import dash
from dash import html
from dash import dcc
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
tab1 = html.Div([
html.H3('Tab 1'),
])
tab2 = html.Div([
html.H3('Tab 2'),
dcc.Dropdown(
id='my-input',
options=[
{'label': 'label_first', 'value': 'first'},
{'label': 'label_second', 'value': 'second'},
],
value='first'
),
html.Div(id='my-output'),
])
app.layout = html.Div([
html.H1('Dash Tabs component demo'),
dcc.Tabs(id="tabs", value='1', children=[
dcc.Tab(label='Overview', value='1'),
dcc.Tab(label='Tab Two', value='2'),
]),
html.Div(id='tab-output')
])
@app.callback(
Output('tab-output', 'children'),
Input('tabs', 'value'))
def render_content(tab):
if tab == '1':
return tab1
elif tab == '2':
return tab2
@app.callback(
Output('my-output', 'figure'),
Input('my-input', 'value'))
def update_div(input_value):
return f'Output: {input_value}'
if __name__ == "__main__":
app.run_server(debug=True)
CodePudding user response:
There is no need to define a callback for rendering the tab contents based on the selected tab, you can just pass the tab layouts (tab1
and tab2
) as children
to each dcc.Tab
. Note also that the component with id='my-output'
is an html.Div
, not a dcc.Graph
, and therefore it doesn't have a figure
property. Once these issues have been fixed the error will go away.
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
tab1 = html.Div([
html.H3('Tab 1'),
])
tab2 = html.Div([
html.H3('Tab 2'),
dcc.Dropdown(
id='my-input',
options=[
{'label': 'label_first', 'value': 'first'},
{'label': 'label_second', 'value': 'second'},
],
value='first'
),
html.Div(id='my-output'),
])
app.layout = html.Div([
html.H1('Dash Tabs component demo'),
dcc.Tabs(id='tabs', value='1', children=[
dcc.Tab(
label='Overview',
value='1',
children=tab1
),
dcc.Tab(
label='Tab Two',
value='2',
children=tab2
),
]),
])
@app.callback(
Output('my-output', 'children'),
Input('my-input', 'value'))
def update_div(input_value):
return f'Output: {input_value}'
if __name__ == '__main__':
app.run_server(debug=True, host='127.0.0.1')
CodePudding user response:
In dash, a callback function is called 3 time that you can look from the official documentation of dash. But for your information every callback function in dash is also called we render the page first time. Here when first time the def update_div(input_value)
callback is called the tab2 is not render on screen. I mean there is no object of tab2 present on screen. So, when parent object is not present on screen its mean, no child object is present on screen. So, this is the reason of the error that you got.
Here is an other solution to your problem.
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
tab1 = html.Div(id='tab1',style={'display':'block'},children=[
html.H3('Tab 1'),
])
tab2 = html.Div(id='tab2',style={'display':'none'}, children=[
html.H3('Tab 2'),
dcc.Dropdown(
id='my_input',
options=[
{'label': 'label_first', 'value': 'first'},
{'label': 'label_second', 'value': 'second'},
],
value='first'
),
html.Div(id='my_output'),
])
app.layout = html.Div([
html.H1('Dash Tabs component demo'),
dcc.Tabs(id="tabs", value='1', children=[
dcc.Tab(label='Overview', value='1'),
dcc.Tab(label='Tab Two', value='2'),
]),
html.Div(id='table_content',children=[tab1,tab2]),
])
@app.callback(
[Output('tab1', 'style'),
Output('tab2', 'style')],
Input('tabs', 'value'))
def render_content(tab):
show = {'display': 'block'}
hide = {'display':'none'}
if tab == '1':
return show, hide
elif tab == '2':
return hide, show
@app.callback(
Output('my_output', 'children'),
Input('my_input', 'value'))
def update_div(input_value):
return f'Output: {input_value}'
if __name__ == "__main__":
app.run_server(debug=True)