I want to automatically set a value in a Multichoice when no value is selected using the set_param()
method (because I want to access to the selector object using its name).
In the following Minimum Reproducible Example, when unselecting a field in a Multichoice, the value updates itself with [“ALL”] using the add_all_if_nothing()
function in the backend but nothing happens graphically.
import pandas as pd
import time
import panel as pn
import holoviews as hv
import numpy as np
import holoviews.plotting.bokeh
from bokeh.models import (
ColumnDataSource,
DataTable,
HTMLTemplateFormatter,
NumberFormatter,
TableColumn,
)
import param
pn.extension(loading_spinner='dots', loading_color='#00aa41', sizing_mode="stretch_width")
hv.extension('bokeh')
pn.param.ParamMethod.loading_indicator = True
class ExclusiveSelector(param.Parameterized):
countries_and_continents = {'countries': {0: 'Abkhazia',
1: 'Afghanistan',
2: 'Akrotiri and Dhekelia',
3: 'Albania',
4: 'Algeria',
5: 'American Samoa',
6: 'Andorra',
7: 'Angola',
8: 'Anguilla',
9: 'Antarctica',
10: 'Antigua and Barbuda',
11: 'Argentina',
12: 'Armenia',
13: 'Aruba',
14: 'Australia',
15: 'Austria',
16: 'Austria-Hungary',
17: 'Azerbaijan',
18: 'Baden',
19: 'Bahamas'},
'continents': {0: 'Asia',
1: 'Asia',
2: 'Asia',
3: 'Europe',
4: 'Africa',
5: 'Oceania',
6: 'Europe',
7: 'Africa',
8: 'North America',
9: 'Antarctica',
10: 'North America',
11: 'South America',
12: 'Asia',
13: 'North America',
14: 'Oceania',
15: 'Europe',
16: 'Europe',
17: 'Asia',
18: 'Europe',
19: 'North America'}}
button = pn.widgets.Button(name="UPDATE", button_type="primary")
df_continents_countries = pd.DataFrame(countries_and_continents)
continents_values = list(df_continents_countries["continents"].unique())
countries_values = list(df_continents_countries["countries"].unique())
continents = param.ListSelector(default=[continents_values[0]], objects= ["ALL"] + continents_values)
countries = param.ListSelector(default=[countries_values[0]], objects= ["ALL"] + countries_values)
selector_values = {
"continents": continents,
"countries": countries
}
def __init__(self, **params):
super().__init__(**params)
self.current_df = self.df_continents_countries
self.settings_panel = pn.Param(
self,
parameters=[
"continents",
"countries"
],
widgets={
"continents": {"type": pn.widgets.MultiChoice},
"countries": {"type": pn.widgets.MultiChoice},
},
)
self.component = pn.Column(self.button, self.settings_panel,
pn.panel(pn.bind(self.update_plot, self.button),
loading_indicator=True))
def get_filters(self):
continents_val = self.continents
countries_val = self.countries
filters = {
"continents": continents_val,
"countries": countries_val,
}
return filters
def add_all_if_nothing(self):
for elem in self.selector_values:
current_f = getattr(self, elem)
print(current_f)
if len(current_f)<1:
print("nothin")
setattr(self, elem, ["ALL"])
self.set_param(elem, ["ALL"])
@param.depends("countries", "continents", watch=True)
def update_fields(self):
self.add_all_if_nothing()
filters = self.get_filters()
df = self.df_continents_countries
for key, inp in filters.items():
if inp != ["ALL"]:
df = df[df[key].isin(inp)]
self.current_df = df
self.build_distinct_fields(df)
return True
def build_distinct_fields(self, df):
self.param.continents.objects = ["ALL"] + list(df["continents"].unique())
self.param.countries.objects = ["ALL"] + list(df["countries"].unique())
def update_plot(self, event):
selected_filters = self.current_df
source = ColumnDataSource(data=selected_filters.to_dict("list"))
columns = []
if event:
time.sleep(2)
for val in self.countries_and_continents:
columns.append(
TableColumn(
field=val,
title=val,
))
return DataTable(source=source, columns=columns)
exc_sel = ExclusiveSelector()
pn.template.FastListTemplate(
site="Panel", title="MRE Exclusive Selector",
main=[exc_sel.component]).servable();
How could this update could be displayed in the Multichoice field so that I have “ALL” selected when I unselect everything ?