Skip to content
Advertisement

Line chart not showing data on multi-page plotly dash

Weird error here. A single page plotly dash shows data on my line chart but when I created a multi page dash, the line chart doesn’t show the data anymore.

enter image description here

just shows this.

Can’t seem to find a way to show the line chart data even though my code is the same.

index.js

app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

nav_item = dbc.NavItem(dbc.NavLink("Home", href="https://www.google.com"))

# make a reuseable dropdown for the different examples
dropdown = dbc.DropdownMenu(
    children=[
        dbc.DropdownMenuItem("Home", href='http://1577.6.0.1:9999/apps/main'),
        dbc.DropdownMenuItem(divider=True),
        dbc.DropdownMenuItem("Login / Sign-Up", href='http://127.0.0.1:8050/apps/test')

    ],
    nav=True,
    in_navbar=True,
    label="Important Links",
)
navbar = dbc.Navbar(
    dbc.Container(
        [
            html.A(
                # Use row and col to control vertical alignment of logo / brand
                dbc.Row(
                    [
                        dbc.Col(dbc.NavbarBrand("something", className="ml-2",)),
                    ],
                    align="center",
                    no_gutters=True,
                ),
                href="https://plot.ly",
            ),
            dbc.NavbarToggler(id="navbar-toggler2"),
            dbc.Collapse(
                dbc.Nav(
                    [
                     nav_item,
                     dropdown,
                     ], className="ml-auto", navbar=True
                ),
                id="navbar-collapse2",
                navbar=True,
            ),
        ]
    ),
    color="#ED4651",
    dark=True,
    className="mb-5",
)

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


@app.callback(Output('page-content', 'children'),
              Input('url', 'pathname'))
def display_page(pathname):
    if pathname == '/apps/login':
        return login.layout
    elif pathname == '/apps/main':
        return main.layout
    else:
        return '404'

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

main.py

state = pd.read_csv("/U********************.csv", index_col=None)

m1 = 0
m2 = 0
m3 = 0



unique = state["Area"].unique()

sq = ["< 500", "500 to 1000", "1000+", "All Sizes"]
sqVal = []



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

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

# assume you have a "long-form" data frame
# see https://plotly.com/python/px-arguments/ for more options

opts = []
for i in unique:
    opts.append({'label': i, 'value': i})

layout = html.Div(children=[
    html.H1(children='stats'),

    html.Div(children='''
        Simple stuff.
    '''),

    dcc.Dropdown(
        id="my-drop",
        options=opts,
        multi=True,
        value=[unique[0]]
    ),
    #html.Button('Update Graph', id='submit-val', n_clicks=0)

    dcc.Graph(id='example-graph')
])

@app.callback(
    Output('example-graph', 'figure'),
    Input('my-drop', 'value'),
)
def update_output_div(input_value):
    check = []
    figures = []
    unique = input_value
    for i in unique:
        m1 = 0
        m2 = 0
        m3 = 0
        for index, row in state.iterrows():
            if (row["Area"] == i):
                if row["Property Type"] == "Commerical":
                    m1 += row["Price"]
                if row["Property Type"] == "Residential":
                    m2 += row["Price"]
                if row["Property Type"] == "Res-Rental":
                    m3 += row["Price"]

        check.extend([m1, m2, m3])

    frames = []

    data = {'Property Type': state["Property Type"].unique()}

    frames.append(pd.DataFrame(data))

    for a in unique:
        newset = []
        for s in range(3):
            newset.append(check[s])

        complete = {a: newset}
        frames.append(pd.DataFrame(complete))

        check = check[3:]

    result = pd.concat(frames, axis=1)

    fig = go.Figure()
    # fig = px.line(result, x=result['Property Type'], y=result[unique[0]], title="Analysis of Price over Property Type")

    # unique = unique[1:]

    for k in unique:
        fig.add_trace(go.Scatter(x=result['Property Type'], y=result[k], name=k,
                                 line_shape='linear'))
        # fig.add_scatter(x=result['Property Type'], y=result[k], name=k)

    fig.update_layout(title="Price by Property Type",
                      xaxis_title="Property Type",
                      yaxis_title="Price",
                      legend_title="Areas")

    return fig

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

New to dash so any help would be amazing. Thank you!

Advertisement

Answer

I can’t confirm because you haven’t shared your imports, but it seems index imports main and main import index.

The way you’ve set it up causes app to not be decorated with the callback function you define inside main.py which results in an empty graph.

There are multiple ways to do it, but one idea is to create a function that takes app as a parameter and decorates it with your callback functions:

# inside main.py
def init_callbacks(app):
    @app.callback(
        Output("example-graph", "figure"),
        Input("my-drop", "value"),
    )
    def update_output_div(input_value):
        # Do stuff...

Then inside index.py you could do something like this:

import main
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

main.init_callbacks(app)

This way app is decorated by the update_output_div callback.


Keep in mind that elements in the main module layout don’t yet exist in app‘s initial layout when main.init_callbacks(app) is executed. So it will probably give you a warning about elements with certain ids not existing in the layout. To prevent this you could add placeholder elements with those ids as children to page-content inside index.py or you could set suppress_callback_exceptions to True.

Advertisement