0
votes

I'm trying to do the following in one single callback:

  1. route the user to the right layout (page_1_layout or page_2_layout) depending on the URL
  2. at the same time, update a dataframe and the relevant graph according to the URL (the idea is that the URL parameter will help filtering the dataframe and generate the related visualization).

According to the Dash documentations, callbacks can produce multiple outputs. In this case, I'm trying to generate the right layout (output #1) and update the graph (output #2). I've tried also using the dataframe as output but that would require the dataframe to be global.

Here's the layout code:

app.layout = html.Div([
    dcc.Location(id='url', refresh=False),
    html.Div(id='page-content')
])


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

page_1_layout = html.Div([
    html.H1('Page 1'),
    html.Div(id='page-1-content'),
    dcc.Graph(id='graph-output'),
    html.Br(),
    dcc.Link('Go to Page 2', href='/WY'),
    html.Br(),
    dcc.Link('Go back to home', href='/'),
])

Here's the callback code:

@app.callback(Output('page-content', 'children'), Output('graph-output', 'figure'), [Input('url', 'pathname')])
def display_page(pathname):
    pathname = str(pathname)
    if pathname.startswith('/CA'):
        country = pathname.split('/')[-1]
        print(country)
        dff = df.loc[df['state'] == country.lower()]
        print(dff)
        fig = px.pie(dff, values='median_listing_price', names="state", title="xxx")
        return page_1_layout, fig
    
    elif pathname == '/WY':
        country = pathname.split('/')[-1]
        print(country)
        dff = df.loc[df['state'] == country.lower()]
        print(dff)
    
        return page_2_layout, fig
    
    else:
        return index_page, fig

This is the error message:

A nonexistent object was used in an Output of a Dash callback. The id >of this object is graph-output and the property is figure. The string >ids in the current layout are: [url, page-content]

I've specified the additional output in the callback, so I'm wondering why it is not recognising it?

1

1 Answers

0
votes

The problem is that the graph-output component does not exist before the page layout is rendered. One solution to the problem would be to render the graph as part of the layout, i.e. something like this,

def render_graph():
    # Put your graph logic here.
    return dcc.Graph(id='graph-output')


def page_1_layout():
    return html.Div([
        html.H1('Page 1'),
        html.Div(id='page-1-content'),
        render_graph(),
        html.Br(),
        dcc.Link('Go to Page 2', href='/WY'),
        html.Br(),
        dcc.Link('Go back to home', href='/'),
    ])