Selecting glyph based on dropdown value

I have a dropdown widget with the options “1”, “2”, and “3”. I’d like to set up a js_on_event so that the glyph in my multi_line plot whose index matches the option clicked is selected – so if I choose, say “2”, the second line on my multi_line plot is selected (and thus highlighted). I tried to implement it like this, but the dropdown doesn’t appear to be doing anything at all.

Also, on a lesser note – is there any way to add a scroll bar to a dropdown for when there are more options than fit on the page?

Hi @RR_Turing ,

Is this a different question than this one?

I think an important thing to remember is that the thing whose selected attribute you’re changing is the ColumnDataSource that provides the data for the glyphs, and not the plot. It looks like you’re passing in your plot to your CustomJS, rather than the CDS.

Hey @carolyn – yes it is, as I am no longer using $name properties for line glyphs but rather ColumnDataSource indices for multi_line. I’ve tinkered around to try and use CDS instead like this, but rather than selecting the index in question all data disappears.

For reference, this is what my CDS looks like (each dictionary value being a list of lists):
image

See if this does what you need:

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

p1 = figure(width=500, height=500)

x =  [0, 1, 2, 3, 4, 5, 6]
y0 = [5, 2, 5, 2, 7, 3, 5]
y1 = [1, 3, 2, 4, 3, 5, 4]
y2 = [9, 6, 8, 3, 5, 9, 8]

source = ColumnDataSource(dict(
    xs=[x, x, x],
    ys=[y0, y1, y2],
))

selector_js = CustomJS(args=dict(cds=source), code="""
    cds.selected.indices = [parseInt(cb_obj.value)]
    console.log(cds.selected.indices) // just for testing, take out if unneeded
""")

mline = p1.multi_line(xs="xs", ys="ys", line_color="orange", line_width=5, source=source)

line_selector = Select(title="Pick a line", value="0", options=["0", "1", "2"])
line_selector.js_on_change("value", selector_js)

col = column(p1, line_selector)

show(col)

Let me know what questions you have!

And re scrollbar in Select: it should automatically place one after a certain point. In my testing, it looks like in a list of 30, it added a scrollbar after element 20 or so. I don’t think there’s a way to manually set that now, but if you’ve got a problem case, show us some screenshots and we can talk about opening an issue!

Unfortunately this does not appear to be doing anything except triggering the non-selection alpha of all my lines. Here’s what it looks like.

The scrollbar does not seem to be triggering for me… see this:

It looks like you want the selection to highlight one of the dotted lines, is that correct? And it looks like it’s only ever highlighting the blue average line. Without an MRE, it’s difficult to know what the issue is, but my first guess would be that it’s something in the way the data is structured not matching up with the way the CustomJS is written.

Are you sure that the cb_obj.value (i.e. the value of the chosen Select element) corresponds to the index of the line you want highlighted in your CDS? Might be helpful to console.log the data structure and cb_obj as you go to make sure, if you’re not doing that already.

I do think that Select config question is worth a GitHub issue. I suspect it decides scrollbar placement based on the space surrounding the widget, so with a lot of vertical space like you show, it has no incentive. Let me know if you’ll put that issue in, or if you’d like me to.

I think it might be that the error might stem from us pulling the index of the list of lists (which would be 0) rather than the index of the list within the list.

Console.log output for

        console.log(cds.selected.indices)

image

Looks to me like your selected.indices contains a non-number. If you’re using the bit of js above that’s parsing an int out of the callback object’s value, you might want to double-check that you’re sending parseInt 1) a string representation of a number, and 2) that the number represents the index of the line you’re aiming for.

This ended up resolving the issue:

    dropdown.js_on_event("menu_item_click", CustomJS(args=dict(cds=source), code="""
        cds.selected.indices = [this.item];
    """))

The only issue remaining is that the dropdown doesn’t have a scrollbar.