Here’s an example. You’re right in that we’re basically replicating the functionality of a CDSView without using that class, since it’s the class that seems to be causing the legend issues.
from bokeh.io import show
from bokeh.models import Slider, CustomJS, ColumnDataSource
from bokeh.plotting import figure
from bokeh.layouts import column
master_cds = ColumnDataSource(data=dict(
x=[1, 2, 3, 4, 5, 6, 7, 8, 9],
y=[3, 2, 1, 3, 2, 1, 3, 2, 1],
color=['red', 'red', 'red', 'green', 'green', 'green', 'blue', 'blue', 'blue'],
group=['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C']
))
subset_cds = ColumnDataSource(data=master_cds.data.copy())
min_x_slider = Slider(start=0, value=0, end=10, step=1)
new_callback = CustomJS(args=dict(master_cds=master_cds, subset_cds = subset_cds, min_x_slider=min_x_slider), code="""
// clear out subset CDS to be rebuilt
subset_cds.clear();
// create a subset CDS by pulling out only the x-values >= our set minimum.
// iterate over the contents of the 'x' array and check for value.
for (i = 0; i < master_cds.data.x.length; i++) {
if (master_cds.data.x[i] > min_x_slider.value) {
subset_cds.data.x.push(master_cds.data.x[i]);
subset_cds.data.y.push(master_cds.data.y[i]);
subset_cds.data.color.push(master_cds.data.color[i]);
subset_cds.data.group.push(master_cds.data.group[i]);
}
};
subset_cds.change.emit();
"""
)
min_x_slider.js_on_change('value', new_callback)
p = figure(x_range=(0, 10), y_range=(-1, 5), plot_height=300, tools='save')
p.circle(x='x', y='y', radius=0.5, color='color', legend_field='group', source=subset_cds)
col = column([p, min_x_slider])
show(col)