The main idea is to collect all line renderes in a list and pass this list to the CustomJS. There you can loop over this list again and apply your changes.
Minimal Example
import pandas as pd
from bokeh.plotting import figure, show, output_notebook
from bokeh.models import CheckboxGroup, CustomJS
from bokeh.layouts import row
output_notebook()
df = pd.DataFrame(
{'x':range(5),
'red':range(5),
'blue':list(range(5))[::-1],
'green':[2]*5}
)
fig = figure(width=300, height=300)
line_renderer = []
names = list(df.columns[1:])
for name in names:
line_renderer.append(
fig.line(
x = 'x',
y = name,
color=name,
name =name,
source=df
)
)
checkbox = CheckboxGroup(labels=names, active=list(range(len(names))), width=100)
callback = CustomJS(args=dict(lines=line_renderer,checkbox=checkbox),
code="""
for(var i=0; i<lines.length; i++){
lines[i].visible = checkbox.active.includes(i);
}
"""
)
checkbox.js_on_change('active', callback)
layout = row(fig,checkbox)
show(layout)
Output