[Solved] Update graph with value of dropdown

Hello everyone.
I have the following map in Dash:

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

mapbox_access_token = 'pk.eyJ1IjoiZ2lsdHJhcG8iLCJhIjoiY2o4eWJyNzY4MXQ1ZDJ3b2JsZHZxb3N0ciJ9.MROnmydnXtfjqjIBtC-P5g'

app = dash.Dash()

app.layout = html.Div([
    html.Div([
        dcc.Graph(
            id = "mapbox",
            figure={
                "data": [
                    dict(
                        type = "scattermapbox",
                        lat = ["45.5017", "46.829853"],
                        lon = ["-73.5673", "-71.254028"],
                        mode = "markers",
                        marker = dict(size = 14),
                        text = ["Montreal", "Quebec"])
                ],
                'layout': dict(
                    autosize = True,
                    hovermode = "closest",
                    margin = dict(l = 0, r = 0, t = 0, b = 0),
                    mapbox = dict(
                        accesstoken = mapbox_access_token,
                        bearing = 0,
                        center = dict(lat = 45, lon = -73),
                        pitch = 0,
                        zoom = 5
                    )
                )
            },
            style = {"height": "100%"}
        )
    ],
        style = {"height": "100%"}
    ),
    html.Div([
        dcc.Dropdown(
            id = "dist-drop",
            options = [{"label": "Montreal", "value": "Montreal"}, {"label": "Quebec", "value": "Quebec"}],
            placeholder = "Select City")
    ],
        style = {"position": "absolute", "top": "50px", "left": "50px", "width": "200px"}
    )
], style = {"border-style": "solid", "height": "95vh"})

app.run_server()

I would like to update the map by selecting one of the options in the dropdown, focusing and zooming in the chosen city. I tried to do this by adding “updatemenus” option in the “layout”, but I get nothing, and also I see another dropdown on one side of the map.

updatemenus = [
                        dict(
                            buttons = ([
                                dict(
                                    args = [dict(center = dict(lat = 45.5017, lon = -73.5673), zoom = 10)],
                                    label = "Montreal",
                                    method = "relayout"
                                ),
                                dict(
                                    args = [dict(center = dict(lat = 46.829853, lon = -71.254028), zoom = 14)],
                                    label = "Quebec",
                                    method = "relayout"
                                )
                            ])
                        )
                    ]

Any idea how I can do it?

Thank you very much.

1 Like

You have no function to update the map. If you add this code before app.run_server() it now takes the value from the dist-drop box and and outputs the result to the figure property of the mapbox
I didn’t change the zoom so that you can have a play some more.

@app.callback(
    Output(component_id='mapbox',component_property='figure'),
    [Input(component_id='dist-drop', component_property='value')]
)
def update_map(city_value):
    #function to deliver lat and lon from value in drop box
    if city_value == 'Montreal':
        latx = ["45.5017"]
        longx = ["-73.5673"]
    else:
        latx = ["46.829853"]
        longx = ["-71.254028"]


    return {
                "data": [
                    dict(
                        type = "scattermapbox",
                        lat = latx,
                        lon = longx,
                        mode = "markers",
                        marker = dict(size = 14),
                        text = city_value)],
                'layout': dict(
                    autosize = True,
                    hovermode = "closest",
                    margin = dict(l = 0, r = 0, t = 0, b = 0),
                    mapbox = dict(
                        accesstoken = mapbox_access_token,
                        bearing = 0,
                        center = dict(lat = 45, lon = -73),
                        pitch = 0,
                        zoom = 5
                    )
                )
            }

Than you for your reply nicktids.

I was trying to figure out how “updatemenus” works, but your solution works perfectly. The only problem I see is that I want to do this on a map with 21 different regions, and I do not know if an if/elif/else function will cause Dash to go slower.

For now I will try your function, to see how it works.

Best regards!

Create a dictionary or a pandas dataframe and reference the index and values.

I do this for mine

initiate / read in a dataframe as df

ind = list(zip(df.city_name,df.index)

		html.Div([
	            dcc.Dropdown(
	                id='city_dropdown',
	                options=[{'label': i[0], 'value': i[1]} for i in ind],
	                multi=True
	            ),

Then within the function you can reference the value from the dropdown box and return the latitude and longitude.

got the idea from this https://plot.ly/dash/gallery/stock-tickers in the gallery. best to start with examples and understand how it works.
https://github.com/plotly/dash-stock-tickers-demo-app

1 Like

You’re right, it’s very helpful to look at the codes in the Dash sample gallery. And I think it’s a better idea to use a dropdown and a function to reference the values of each city, than to use the buttons and the “updatemenus” function, since they are a lot of cities.

Thank you very much for your help, nicktids!

1 Like