Hi everyone,
This is my first post in the discourse, so excuse me if I don’t follow protocol here…
I am building a feature, where I’d like the widgets in a template sidebar to be updated depending on which tab is active. Given my understanding of Panel, I thought the best way to achieve this is via a callback/linking.
I can’t share the exact code for compliance reasons, but I created a dummy example (leveraging https://panel.holoviz.org/user_guide/Templates.html ) and a dummy callback. However, it doesn’t seem to work.
Am I missing something here? Or is such a feature not supported?
Any input is greatly appreciated. Thank you all and excited to be part of this community.
import panel as pn
import holoviews as hv
import numpy as np
pn.extension()
hv.extension('bokeh')
pn.config.sizing_mode = 'stretch_width'
def insert_widget(target, event):
active_tab_idx = event.new
target.objects.insert(active_tab_idx, freq)
bootstrap = pn.template.BootstrapTemplate(title='Bootstrap Template')
xs = np.linspace(0, np.pi)
freq = pn.widgets.FloatSlider(name="Frequency", start=0, end=10, value=2)
phase = pn.widgets.FloatSlider(name="Phase", start=0, end=np.pi)
@pn.depends(freq=freq, phase=phase)
def sine(freq, phase):
return hv.Curve((xs, np.sin(xs*freq+phase))).opts(
responsive=True, min_height=400)
@pn.depends(freq=freq, phase=phase)
def cosine(freq, phase):
return hv.Curve((xs, np.cos(xs*freq+phase))).opts(
responsive=True, min_height=400)
bootstrap.sidebar.append(freq)
bootstrap.sidebar.append(phase)
tabs = pn.Tabs(dynamic=True, active=0)
tabs.append(('Sine', pn.Card(hv.DynamicMap(sine), title='Sine')))
tabs.append(('Cosine', pn.Card(hv.DynamicMap(cosine), title='Cosine')))
tabs.link(bootstrap.sidebar, callbacks={'active': insert_widget})
bootstrap.main.append(tabs)
bootstrap.show()
nghenzi
December 11, 2020, 5:03pm
2
Welcome ! I am not so familiar with the link method, instead I prefer to use the pn.depends decorators. In that case, you can populate the sidebar with a pn.Column and with a callback you can replace the elements in that pn.Column object. I think the pn.Column object like a simple python list, then you can replace the panel object in the list so simply like replacing the elements. In this case you have only one element, but it can be the quantity you want. The working example is
import panel as pn
import holoviews as hv
import numpy as np
pn.extension()
hv.extension('bokeh')
pn.config.sizing_mode = 'stretch_width'
bootstrap = pn.template.BootstrapTemplate(title='Bootstrap Template')
xs = np.linspace(0, np.pi)
freq = pn.widgets.FloatSlider(name="Frequency", start=0, end=10, value=2)
phase = pn.widgets.FloatSlider(name="Phase", start=0, end=np.pi)
@pn.depends(freq=freq, phase=phase)
def sine(freq, phase):
return hv.Curve((xs, np.sin(xs*freq+phase))).opts(
responsive=True, min_height=400)
@pn.depends(freq=freq, phase=phase)
def cosine(freq, phase):
return hv.Curve((xs, np.cos(xs*freq+phase))).opts(
responsive=True, min_height=400)
col = pn.Column(freq)
bootstrap.sidebar.append(col)
tabs = pn.Tabs(dynamic=True, active=0)
tabs.append(('Sine', pn.Card(hv.DynamicMap(sine), title='Sine')))
tabs.append(('Cosine', pn.Card(hv.DynamicMap(cosine), title='Cosine')))
@pn.depends(tabs.param.active, watch=True)
def insert_widget(active_tab):
print (active_tab)
if active_tab == 0:
col[0] = freq
else:
col[0] = phase
bootstrap.main.append(tabs)
bootstrap.show()
1 Like
nghenzi
December 11, 2020, 5:49pm
3
AndrewMe:
target, event
This is the same example with the link method. it is noteworthy to mention you can use col.append() to add elements dinamically to the sidebar.
import panel as pn
import holoviews as hv
import numpy as np
pn.extension()
hv.extension('bokeh')
pn.config.sizing_mode = 'stretch_width'
bootstrap = pn.template.BootstrapTemplate(title='Bootstrap Template')
xs = np.linspace(0, np.pi)
freq = pn.widgets.FloatSlider(name="Frequency", start=0, end=10, value=2)
phase = pn.widgets.FloatSlider(name="Phase", start=0, end=np.pi)
@pn.depends(freq=freq, phase=phase)
def sine(freq, phase):
return hv.Curve((xs, np.sin(xs*freq+phase))).opts(
responsive=True, min_height=400)
@pn.depends(freq=freq, phase=phase)
def cosine(freq, phase):
return hv.Curve((xs, np.cos(xs*freq+phase))).opts(
responsive=True, min_height=400)
col = pn.Column(freq)
bootstrap.sidebar.append(col)
tabs = pn.Tabs(dynamic=True, active=0)
tabs.append(('Sine', pn.Card(hv.DynamicMap(sine), title='Sine')))
tabs.append(('Cosine', pn.Card(hv.DynamicMap(cosine), title='Cosine')))
def insert_widget( target, event):
print (event.new)
if event.new == 0:
col[0] = freq
else:
col[0] = phase
tabs.link(col, callbacks={'active': insert_widget})
bootstrap.main.append(tabs)
bootstrap.show()
2 Likes