HTML output shows locally, but not when accessed via local server

Hello Dash Community,

I’m excited to have my dash app up and running on a local server accessible throughout our office, but there is one issue: The HTML output from the code that normally shows up in a new tab after making selections and clicking the submit button, does not show up for a user viewing the web app via the server.

Note: plotly_figure_player_scorecard is a function that makes scorecards for different sections of a player’s performance: batting, fielding, pitching, etc.

Note: variable names were changed for this post so there could be some typos, be assured that the code runs properly.

My hypothesis is that it is because I use:

plotly.offline.plot(output_fig, filename = ‘overall_plotly_viz_for_’ + player+ ‘.html’) to generate the plotly results. in the following function:

def ov_player_scorecard_viz(player):
    '''
    Create a player scorecard

    Args:
        usr: A user
    Return:
        A web app where the user can select a team and a player
    '''
    bar_list = []
    button_list = []
    player_figure_list = plotly_figure_player_scorecard(player)
    visibility_list = list(range(0,len(player_figure_list)))

    i = 0
    for figure, section, color in zip(player_figure_list, section_title_list, section_color_list):
        print(i)
        figure['data'][0]['name'] = section.replace('_', ' ')
        figure['data'][0]['marker']['color']  = color
        figure['data'][0]['x'] = ('Player', 'Team Average', 'Region Average', 'League Average')
        bar_list.append(figure['data'][0])

        fig_button = dict(label = section.replace('_', ' '),
                          method = 'update',
                          args = [{'visible': [k== i for k in visibility_list]},
                                  {'title': section}
                                 ]
                         )
        button_list.append(fig_button)
        i += 1

    data = bar_list

    # Adding Reset Buttons
    reset_button = dict(label = 'Overall',
                        method = 'update',
                        args = [{'visible': [k != -1 for k in visibility_list]},
                               {'title': 'Player Scorecard: ' + player}
                               ]
                       )

    button_list.append(reset_button)

    updatemenus = list([
        dict(active = 18,
             buttons = button_list,
             direction = 'down',
             pad = {'r': 40, 't': 0},
             y = 1   # 0.25 is a good location for the next dropdown
        )
    ])

    layout = dict(title= 'Player Scorecard: ' + player,
                  showlegend=True,
                  updatemenus=updatemenus
                 )

    output_fig = dict(data=data, layout = layout)
    plotly.offline.plot(output_fig, filename = 'overall_plotly_viz_for_' + player + '.html')

Then we implement dash

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

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

key_list = []
val_list = []
for team in all_team_df['Analysis_Team'].unique():
    key = str(team)
    val = all_team_df[all_team_df['Analysis_Team'] == team]['Player_Name'].unique().tolist()
    key_list.append(key)
    val_list.append(val)

# Create a dictionary with key value pairs of  Region: Team list
all_options = dict(zip(key_list, val_list))

app.layout = html.Div([
    html.Div([
        html.Span('{Players', style={'font-size': 'xx-large',
                                     'font-family': 'Segoe UI',
                                     'color': '#0072BC'
                                    }
        ),             # Cubs Blue
        html.Span('&Scores', style={'font-size': 'xx-large',
                                'font-family': 'Segoe UI',
                                'color': '#aaaaaa'  # Logo Gray
                               }
        ),
    ],
        style={'textAlign': 'center'}
    ),

    html.Hr(),


    html.Div([
        html.Span('Select a Team', style={'font-size': 'xx-large',
                                          'font-family': 'Segoe UI',
                                          'color': '#445663' #Dark blue
                                         }
        )
    ],
        style={'textAlign': 'center'}
    ),

    dcc.Dropdown(
        id='Teams-dropdown',
        options=[{'label': k, 'value': k} for k in all_options.keys()],
        value= key_list[0],
        style={
                'width' : '400px',
                'display': 'inline-block',
        }
    ),

    html.Hr(),
    html.Div([
        html.Span('Select a Player', style={'font-size': 'xx-large',
                                            'font-family': 'Segoe UI',
                                            'color': '#445663' # Dark blue
                                           }
        )
    ],
        style={'textAlign': 'center'}
    ),

    dcc.Dropdown(id='players-dropdown',
        value = val_list[0][0].replace('_', ' '),
        style={
            'width' : '400px',
            'display': 'inline-block',
        }
    ),
    html.Hr(),
    html.Button('Submit', n_clicks=0, id='button'),
    html.Div(id='display-selected-values')
],
    style={'textAlign': 'center'}
)


@app.callback(
    Output('players-dropdown', 'options'),
    [Input('Teams-dropdown', 'value')])
def set_teams_options(selected_team):
    return [{'label': i, 'value': i} for i in all_options[selected_team]]


@app.callback(
    Output('players-dropdown', 'value'),
    [Input('players-dropdown', 'options')])
def set_players_value(available_options):
    return available_options[0]['value']


@app.callback(
    Output('display-selected-values', 'children'),
    [Input('button', 'n_clicks')],
    state = [State(component_id = 'Teams-dropdown',  component_property='value'),
             State(component_id = 'players-dropdown',  component_property='value')]
    )

def set_display_children(n_clicks, selected_Team, selected_player):
    if n_clicks > 0:
        ov_player_scorecard_viz(selected_player)
        return u'{} is a player of team {}'.format(
            selected_player, selected_Team)
    else:
        return 'Please select a Team and player.'


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

wsgi.py is as follows:

from player_scorecards import server as application

Edit: Updated formatting, again. New to forum formatting.

Your hypothesis might be correct - as far as I know, running plotly.offline.plot just opens the thing in the most recent local default browser window. Have you tried returning the figure in a dcc.Graph in the dash app itself? That will show for your user on a server.

# function definition
def ov_player_scorecard_viz(selected_player):
    ...
    return output_fig
...
from dash import Dash, no_update

# app
app.layout = html.Div([
    ...
    dcc.Graph(id='output-graph',)
    ...
])

@app.callback(
    [Output('display-selected-values', 'children'),
        Output('output-graph','figure')],
    [Input('button', 'n_clicks')],
    [State(component_id = 'Teams-dropdown',  component_property='value'),
             State(component_id = 'players-dropdown',  component_property='value')]
    )
def set_display_children(n_clicks, selected_Team, selected_player):
    if n_clicks > 0:
        return \
            u'{} is a player of team {}'.format(
                selected_player, selected_Team
            ),
            ov_player_scorecard_viz(selected_player)
    else:
        return 'Please select a Team and player.', no_update
1 Like

This worked wonders. Thank you! :smile:

1 Like