Bokeh - Update plot with Select widget and CustomJS

I am trying to display a bar chart and have the contents filtered by a Select object. As simple as it seems, I have not been able to find a working solution after two days of looking. I need to do this with CustomJS, not bokeh server.

Here is the code I am trying, but when I run it nothing is displayed, not even an empty plot.

import pandas as pd
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, CustomJS, CustomJSFilter, CDSView, Select, IndexFilter
from bokeh.io import show, output_notebook
from bokeh.layouts import column
output_notebook()

df = pd.DataFrame({'Subject': ['Math', 'Math', 'Math', 'Science', 'Science', 'Science'],
                  'Class': ['Algebra', 'Calculus', 'Trigonometry', 'Biology', 'Chemistry', 'Physics'],
                  'FailRate': [0.05, 0.16, 0.31, 0.12, 0.20, 0.08]})

src = ColumnDataSource(df)

subj_list = sorted(list(set(src.data['Subject'])))

callback = CustomJS(args=dict(src=src), code='''
    src.change.emit();
''')

js_filter = CustomJSFilter(code='''
var indices = [];
for (var i = 0; i < src.get_length(); i++){
    if (src.data['Subject'][i] == select.value){
        indices.push(true);
    } else {
        indices.push(false);
    }
}
return indices;
''')

options = ['Please select...'] + subj_list
select = Select(title='Subject Selection', value=options[0], options=options)

select.js_on_change('value', callback)

view = CDSView(source=src, filters=[js_filter])

class_list = sorted(list(src.data['Class']))

p = figure(x_range=class_list, plot_height=400, plot_width=400) 
p.vbar('Class', top='FailRate', width=0.9, source=src, view=view)

show(column(select, p))

As far as I can tell, part of the problem involves this line (or the ‘view’ variable):

p.vbar('Class', top='FailRate', width=0.9, source=src, view=view)

Before I added ‘view=view’ to the above line, I was at least getting a select box and plot displayed, even though the interaction was not working.

I answered on Stack Overflow. Please, if you must cross-post, always state that and include a link to the other post.

My apologies, I didn’t realize this was frowned upon. Here is the link to the SO thread:

Just for context, the issue is that as maintainers we do not want to leave unanswered questions hanging around (bad look), but it’s obviously more of a burden to try and check and cover multiple venues.

Thanks for the very useful and simple customjs. My dropdown includes an ‘All’ option to resume the plot with all the data in source, that is using all indices:
callback = CustomJS(args=dict(source=source, filter=filter), code=’’’
var indices =
var selected_value = cb_obj.value
if (selected_value==‘All’) {
indices = source.index
console.log (‘all ccgs selected’)
} else {
console.log(‘selected ccg= ’ + selected_value)
for (var i = 0; i < source.get_length(); i++) {
// console.log(i, source.data[‘ccg’][i], cb_obj.value)
if (source.data[‘ccg’][i] == selected_value) {
indices.push(i)
}
}
}
filter.indices = indices
source.change.emit()
‘’’)
Clicking ‘All’ I’m getting all the data but the console states:

[bokeh] IndexFilter 1003: indices was not set, defaulting to no filtering

Can you tell me how to access the index of my data in source? Obviously source.index is not the way, but I search and didn’t find the right way.