Use two different widgets to update same plot

Hello,

Let’s say I have a small dashboard like the one marked (Version 1) in this image

which was created with the following code:

import panel as pn
import numpy as np
import holoviews as hv
pn.extension()
_continents = ['Asia','Europe','America']
_cities     = {'Asia':['Singapore','Seoul','Shanghai'],
              'America':['Boston','Toronto','Quito','Santiago'],
              'Europe':['Madrid','London','Paris','Lisbon']}
select_continent = pn.widgets.Select(name='Continent',options=_continents, value=_continents[0])
select_city      = pn.widgets.Select(name='City',     options=_cities[select_continent.value], value=_cities[select_continent.value][0])
@pn.depends(select_continent.param.value, watch=True)
def _update_cities(continent):
    cities = _cities[continent]
    select_city.options = cities
    select_city.value = cities[0]
@pn.depends(select_city.param.value)
def get_plot(city):
    data = np.random.rand(100)
    return hv.Curve(data).opts(title=city, width=500)
pn.Column(pn.Row(select_continent,select_city), get_plot)

I would like to modify this dashboard, so that users can also select the city via an alternative AutocompleteInput widget (Dashboard Version 2 in image above). In other words, I want to provide users with two options in order to select city:

a) use two selectors, to first select continent, and then city (from the cities of the selected continent),
b) directly type the city they want to select.

How do I modify the above code to have this extra functionality?

I can add the extra GUI elements as follows:

_all_cities = ['Singapore','Seoul','Shanghai','Boston','Toronto','Quito','Santiago','Madrid','London','Paris','Lisbon']
autocomplete_city = pn.widgets.AutocompleteInput(name='City',options=_all_cities)
pn.Column(pn.Tabs(('Per Continent',pn.Row(select_continent, select_city)),('Autocomplete',autocomplete_city)), get_plot)

But I don’t know how to code all the necessary dependences between GUI elements so that when a user types into the autocomplete box, that automatically updates the continent select, city select and graph.

Thanks a lot for any guidance you can provide,

Best,

Javier.

Hi @javiergcas

This can be solved in different ways.

The solution below is based on keeping the code as close to your initial approach as possible. It uses the select_city widget as the one source of truth of the currently selected city triggering an update of the plot.

import panel as pn
import numpy as np
import holoviews as hv
pn.extension()

_continents = ['Asia','Europe','America']
_cities     = {'Asia':['Singapore','Seoul','Shanghai'],
              'America':['Boston','Toronto','Quito','Santiago'],
              'Europe':['Madrid','London','Paris','Lisbon']}

def transform(_cities):
    continents_lookup = {}
    cities_list = []
    for continent, cities in _cities.items():
        for city in cities:
            continents_lookup[city]=continent
    cities_list = list(continents_lookup.keys())
    return continents_lookup, cities_list
_continents_lookup, _cities_list = transform(_cities)

select_continent = pn.widgets.Select(name='Continent',options=_continents, value=_continents[0])
select_city      = pn.widgets.Select(name='City',     options=_cities[select_continent.value], value=_cities[select_continent.value][0])
select_city_auto = pn.widgets.AutocompleteInput(name='City', options=_cities_list, value = select_city.value)

@pn.depends(select_continent.param.value, watch=True)
def _update_cities(continent):
    cities = _cities[continent]
    select_city.options = cities
    select_city.value = cities[0]

@pn.depends(select_city_auto.param.value, watch=True)
def _update_from_auto_complete(city):
    select_continent.value = _continents_lookup[city]
    select_city.value = city

@pn.depends(select_city.param.value, watch=True)
def _update_auto_complete(city):
    select_city_auto.value = city

@pn.depends(select_city.param.value)
def get_plot(city):
    data = np.random.rand(100)
    return hv.Curve(data).opts(title=city, width=500)

pn.Column(
    pn.Tabs(
        pn.Row(select_continent, select_city, name="By Continent"),
        pn.Row(select_city_auto, name="Autocomplete")
    ),
    get_plot
).servable()
3 Likes

Thanks so much @Marc . This is exactly what I was looking for.

Javier.

1 Like

Hi @javiergcas. I’ve added your example to awesome-panel.org

https://awesome-panel.org/dependent-widgets?theme=default

https://awesome-panel.org/dependent-widgets?theme=dark

2 Likes