Scatter plot tap event to change dropdown

Hi I have a dropdown that control the scatter plot with hv.DynamicMap(
I have added tools=[‘tap’]
is there a way that a tap on the chart will change the selection on the dropdown dynmicaly ?
instaed of just the dropdown to control the chart the chart to contorl the dropdown as weel?
thanks

Yeah a basic CustomJS should be able to accomplish this.

The key thing to wrap your head around is that the tap even changes the selected.indices property of the source that’s driving the renderer you just tapped. So basically when they select something, we just need to retrieve the corresponding value at that record in the source and update the dropdown menu accordingly.

I added a second callback to “go the other way” → i.e. when the user clicks a dropdown value, select all datasource values that have that value as well (not sure if you wanted that as well).

from bokeh.plotting import figure, show
from bokeh.layouts import column
from bokeh.models import Dropdown, CustomJS,ColumnDataSource

src = ColumnDataSource(data={'X':[0,1,2,3],'Y':[5,2,3,1],'Value':['Banana','Apple','Orange','Banana']})

f = figure(tools=['tap'])

r = f.scatter(x='X',y='Y',size=15,source=src)

dd = Dropdown(label='Click a Point',menu=[('Banana','Banana'),('Apple','Apple'),('Orange','Orange')])

#when selected index changes from clicking a point...
cb = CustomJS(args=dict(src=src,dd=dd)
              ,code='''
              //get the selected index
              var sel_ind = src.selected.indices[0]
              // get the value that corresponds to
              var val = src.data['Value'][sel_ind]
              //update the dropdown label
              dd.label = val
              ''')
src.selected.js_on_change('indices',cb)

#and then going the other way, if user changes dropdown value...
dd.js_on_event('menu_item_click',CustomJS(args=dict(src=src,dd=dd)
                                          ,code='''
                                          //get the value of the dd menu that's chosen
                                          var val = this.item
                                          //update the dd label to reflect this
                                          dd.label = val
                                          //collect indices in the source where this value exists
                                          var sel_inds = []
                                          for (var i=0;i<src.data['Value'].length;i++){
                                                  if (src.data['Value'][i]==val){
                                                          sel_inds.push(i)}
                                                  }
                                          //update the selected indices with that
                                          src.selected.indices = sel_inds
                                          src.change.emit
                                          '''))

show(column([f,dd]))
2 Likes