✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🐇 Announcing Dash VTK for 3d simulation graphics. Check out the March webinar.

Assign callback to component on different page

It is not possible to assign a component/ID to a callback which is not part of the app.layout object.
I need to create a site where 3 pages are able to trigger callback functions which update the data on another page, Is there any solution to this?

import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
import time
from dash.dependencies import Input, Output, State

#load CSS
external_stylesheets = [dbc.themes.BOOTSTRAP, 'https://codepen.io/chriddyp/pen/bWLwgP.css']
#make dash app object
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config.suppress_callback_exceptions = False

#app layout
app.layout = html.Div([
   dcc.Location(id='url', refresh=False),
   dbc.Modal(
       [
           dbc.ModalHeader("END OF COMPLEX OPERATIONS"),
           dbc.ModalBody("Finally!"),
       ],
       id='end-modal',
       is_open=False,
   ),
   html.Div(id='page-content'),
])

#Definition of index page
index_page = html.Div([
   dcc.Link('Go to Page 1', href='/page-1'),
   html.Br(),
   dcc.Link('Go to Page 2', href='/page-2'),
])

#definition of page 1
page_1_layout = ([  
   dcc.Graph(
       id='example-graph2',
       figure={
           'data': [
               {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
               {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'},
           ],
           'layout': dict
               (
               xaxis={'type': 'log', 'title': 'GDP Per Capita', 'gridcolor' : '000000'},
               yaxis={'title': 'Life Expectancy', 'gridcolor' : '000000'},
               margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
               legend={'x': 0, 'y': 1},
               hovermode='closest',
               paper_bgcolor='rgba(001,0,0)',
               plot_bgcolor='rgba(1,0.2,1,0.5)',
               font=dict
               (
               family="Vedrana, monospace",
               size=12,
               color="#EEEEEE"
               )
               )
       }
   ),
])

#definition of page 2
page_2_layout =  html.Div([   
   dcc.Slider(
       id='my-slider',
       min=0,
       max=1,
       step=0.1,
       value=0.3,
   ),
   html.Div(id='slider-output-container')
])


#definition of page 3
page_3_layout = html.Div([
   'Some more stufff!!!!'
])


#when slider changes update graph
@app.callback(
   dash.dependencies.Output(component_id='example-graph2', component_property='figure'),
   [dash.dependencies.Input('my-slider', 'value')])
def update_output(value):
   print('callback triggered')
   return {
           'data': [
               {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
               {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'},
           ],
           'layout': dict
               (
               xaxis={'type': 'log', 'title': 'GDP Per Capita', 'gridcolor' : '000000'},
               yaxis={'title': 'Life Expectancy', 'gridcolor' : '000000'},
               margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
               legend={'x': 0, 'y': 1},
               hovermode='closest',
               paper_bgcolor='rgba(001,0,0)',
               plot_bgcolor='rgba(1,0.2,1,1)',
               font=dict
               (
               family="Vedrana, monospace",
               size=value,
               color="#EEEEEE"
               )
               )
       }




# Update the index
@app.callback(dash.dependencies.Output('page-content', 'children'),
             [dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
   if pathname == '/page-1':
       return page_1_layout
   elif pathname == '/page-2':
       return page_2_layout
   elif pathname == '/page-3':
       return page_3_layout
   else:
       return index_page

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

In this case I am trying to trigger a callback event when the value of the slider has changed on page2, and the function will modify the figure of the graph on page 1.

If I include the slider and the graph in the app.layout class, they are able to reference eachother, but will be visible on each page.

One possible solution would be to store state (in your case, the position of the slider) in a Store object,

...
html.Div(id='page-content'),
dcc.Store(id='my-store')
...

You could then add the store as a State element in you “display_page” function and pass the data to the page. Your current page layout variables, e.g. the “page_1_layout”, should then be change to functions that take the data as input.

Hi Emil, Thanks for the reply, Ill try this out and post the results

edit: ok got this working, here is a basic example:

import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
import time
import dash
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate


external_stylesheets = [dbc.themes.BOOTSTRAP, 'https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.config.suppress_callback_exceptions = True

app.layout = html.Div([
    dcc.Store(id='store_slider', storage_type='local', data='SlideValue'),
    dcc.Location(id='url', refresh=False),
    dbc.Modal(
        [
            dbc.ModalHeader("END OF COMPLEX OPERATIONS"),
            dbc.ModalBody("Finally!"),
        ],
        id='end-modal',
        is_open=False,
    ),
    html.Div(id='page-content')
])

index_page = html.Div([
    dcc.Link('Go to Page 1', href='/page-1'),
    html.Br(),
    dcc.Link('Go to Page 2', href='/page-2'),
])

page_1_layout = html.Div([
    dcc.Textarea(
        id='text',
        value='Value of slider?'
    )
])

page_2_layout = html.Div([   
   dcc.Slider(
       id='slider',
       min=0,
       max=1,
       step=0.1,
       value=0.3,
   ),
   html.Div(id='slider-output-container')
])

page_3_layout = html.Div([
    'Some more stufff!!?!'
])


@app.callback(Output('store_slider', 'data'),
              [Input('slider','value')],
              [State('store_slider', 'data')])
def update_slider(value, data):
    print(f'changed slider to {value}')
    data = str(value)
    return data


@app.callback(Output('text','value'),
            [Input('store_slider', 'modified_timestamp')],
            [State('store_slider', 'data')])
def updatetext(timestamp, data):
    print('triggered store')
    return data





# Update the index
@app.callback(dash.dependencies.Output('page-content', 'children'),
              [dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):


    if pathname == '/page-1':
        return page_1_layout
    elif pathname == '/page-2':
        return page_2_layout
    elif pathname == '/page-3':
        return page_3_layout
    else:
        return index_page


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