Black Lives Matter. Please consider donating to Black Girls Code today.

Figure Callback doesn't work with url as input

I’ve been working on a multi-page app in healthcare and it servers 2 pages: 1 with an overview of patients, the other with an in depth view of a single patient when clicked on it.
So when clicking on a patient, it’s a href like url.com/31 with 31 being the patient’s unique ID.

Now I’d like it when a user clicks on a patient, the in-depth graphs on that patient are loaded immediately. To make this, I created a callback with url, pathname as input and figure-id, figure as output. So you’d expect that when the url changes from / to /31, it triggers a callback to generate the figure needed based on the number in the url.

That’s not what I see. When I trigger the same function with a button and use url as state input it works perfectly fine. When using url input and text output, it works as expected too. Just not with a figure.

I’ve created a reproducible example from a mashup between the example here: https://dash.plot.ly/urls and here https://dash.plot.ly/getting-started

It’s a 2 page app. The callbacks to look at are called example_1 and example_2. Both have the exact same input, only example_1 outputs to a div with text and example_2 to a graph. You can click around and see that example_1 only triggers when we get to page-1. Example-2 only gets triggered when going back to /. Not when going from / to /page-1

import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go

df = pd.read_csv(
    'https://raw.githubusercontent.com/plotly/'
    'datasets/master/gapminderDataFiveYear.csv')

print(dcc.__version__) # 0.6.0 or above is required

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

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

# Since we're adding callbacks to elements that don't exist in the app.layout,
# Dash will raise an exception to warn us that we might be
# doing something wrong.
# In this case, we're adding the elements through a callback, so we can ignore
# the exception.
app.config.suppress_callback_exceptions = True

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='/page-1'),
    html.Br(),
    dcc.Link('Go to Page 2', href='/page-2'),
])

page_1_layout = html.Div([
    html.H1('Page 1', id='title'),
    dcc.Dropdown(
        id='page-1-dropdown',
        options=[{'label': i, 'value': i} for i in ['LA', 'NYC', 'MTL']],
        value='LA'
    ),
    html.Div(id='page-1-content'),
    html.Div(id='page-1-content-2'),
    dcc.Graph(id='graph-with-slider'),
    html.Br(),
    dcc.Link('Go to Page 2', href='/page-2'),
    html.Br(),
    dcc.Link('Go back to home', href='/'),
])



@app.callback(dash.dependencies.Output('page-1-content', 'children'),
              [dash.dependencies.Input('page-1-dropdown', 'value')])
def page_1_dropdown(value):
    return 'You have selected "{}"'.format(value)

@app.callback(dash.dependencies.Output('page-1-content-2', 'children'),
              [dash.dependencies.Input('url', 'pathname')])
def example_1(pathname):
    print('example_1 triggered!')
    return "You're on the url: {}".format(pathname)


@app.callback(
    dash.dependencies.Output('graph-with-slider', 'figure'),
    [dash.dependencies.Input('url', 'pathname')])
def example_2(selected_year):
    print('example_2 triggered!')
    filtered_df = df[df.year == 2007]
    traces = []
    for i in filtered_df.continent.unique():
        df_by_continent = filtered_df[filtered_df['continent'] == i]
        traces.append(go.Scatter(
            x=df_by_continent['gdpPercap'],
            y=df_by_continent['lifeExp'],
            text=df_by_continent['country'],
            mode='markers',
            opacity=0.7,
            marker={
                'size': 15,
                'line': {'width': 0.5, 'color': 'white'}
            },
            name=i
        ))

    return {
        'data': traces,
        'layout': go.Layout(
            xaxis={'type': 'log', 'title': 'GDP Per Capita'},
            yaxis={'title': 'Life Expectancy', 'range': [20, 90]},
            margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
            legend={'x': 0, 'y': 1},
            hovermode='closest'
        )
    }


page_2_layout = html.Div([
    html.H1('Page 2'),
    dcc.RadioItems(
        id='page-2-radios',
        options=[{'label': i, 'value': i} for i in ['Orange', 'Blue', 'Red']],
        value='Orange'
    ),
    html.Div(id='page-2-content'),
    html.Br(),
    dcc.Link('Go to Page 1', href='/page-1'),
    html.Br(),
    dcc.Link('Go back to home', href='/')
])


@app.callback(dash.dependencies.Output('page-2-content', 'children'),
              [dash.dependencies.Input('page-2-radios', 'value')])
def page_2_radios(value):
    return 'You have selected "{}"'.format(value)


# 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
    else:
        return index_page
    # You could also return a 404 "URL not found" page here


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

What am I missing? Also: I love dash, so if this is a real bug, I might go search for it and fix it myself with a PR if I can!