Adding widgets¶
Widgets are interactive controls that can be added to Bokeh applications to provide a front end user interface to a visualization. They can drive new computations, update plots, and connect to other programmatic functionality. When used with the Bokeh server, widgets can run arbitrary Python code, enabling complex applications. Widgets can also be used without the Bokeh server in standalone HTML documents through the browser’s JavaScript runtime.
Callbacks¶
To use widgets, you must add them to your document and define their callbacks. Widgets can be added directly to the document root or nested inside a layout. There are two ways to use a widget’s functionality:
A
CustomJS
callback (see JavaScript callbacks). This approach will work in standalone HTML documents or Bokeh server apps.Use
bokeh serve
to start a Bokeh server and set up event handlers with.on_change
(or for some widgets,.on_click
).
Event handlers are Python functions that users can attach to widgets. These
functions are then called when certain attributes on the widget are changed.
The function signature of event handlers is determined by how they are attached
to widgets (whether by .on_change
or .on_click
, for example).
All widgets have an .on_change
method that takes an attribute name and one
or more event handlers as parameters. These handlers are expected to have the
function signature, (attr, old, new)
, where attr
refers to the changed
attribute’s name, and old
and new
refer to the previous and updated
values of the attribute.
def my_text_input_handler(attr, old, new):
print("Previous label: " + old)
print("Updated label: " + new)
text_input = TextInput(value="default", title="Label:")
text_input.on_change("value", my_text_input_handler)
Additionally, some widgets, including the button, dropdown, and checkbox, have
an .on_click
method that takes an event handler as its only parameter. For
a plain Button
, this handler is called without parameters. For the other
widgets with .on_click
, the handler is passed the new attribute value.
def my_radio_handler(new):
print('Radio button option ' + str(new) + ' selected.')
radio_group = RadioGroup(labels=["Option 1", "Option 2", "Option 3"], active=0)
radio_group.on_click(my_radio_handler)
Bokeh provides a simple default set of widgets. Users can create their own custom widgets, or wrap different third party widget libraries by creating custom extensions as described in Extending Bokeh.
For more information about the attributes to watch using .on_change
, see the
reference guide. (Information about widgets is found under bokeh.models.)
Examples¶
The sections below collect short but complete examples of using all the built-in widgets. Many of the examples print output that can be observed by looking at your browser JavaScript console log.
Button¶
Bokeh provides a simple Button:
from bokeh.io import show
from bokeh.models import Button, CustomJS
button = Button(label="Foo", button_type="success")
button.js_on_click(CustomJS(code="console.log('button: click!', this.toString())"))
show(button)
More information can be found in the Reference for Button
.
CheckboxButtonGroup¶
Bokeh also provides a checkbox button group, that can have multiple options selected simultaneously:
from bokeh.io import show
from bokeh.models import CheckboxButtonGroup, CustomJS
LABELS = ["Option 1", "Option 2", "Option 3"]
checkbox_button_group = CheckboxButtonGroup(labels=LABELS, active=[0, 1])
checkbox_button_group.js_on_click(CustomJS(code="""
console.log('checkbox_button_group: active=' + this.active, this.toString())
"""))
show(checkbox_button_group)
More information can be found in the Reference for CheckboxButtonGroup
.
CheckboxGroup¶
A standard checkbox:
from bokeh.io import show
from bokeh.models import CheckboxGroup, CustomJS
LABELS = ["Option 1", "Option 2", "Option 3"]
checkbox_group = CheckboxGroup(labels=LABELS, active=[0, 1])
checkbox_group.js_on_click(CustomJS(code="""
console.log('checkbox_group: active=' + this.active, this.toString())
"""))
show(checkbox_group)
More information can be found in the Reference for CheckboxGroup
.
ColorPicker¶
A widget to allow the user to specify an RGB color value.
from bokeh.io import show
from bokeh.layouts import column
from bokeh.models import ColorPicker
from bokeh.plotting import Figure
plot = Figure(x_range=(0, 1), y_range=(0, 1), width=350, height=350)
line = plot.line(x=(0,1), y=(0,1), color="black", line_width=4)
picker = ColorPicker(title="Line Color")
picker.js_link('color', line.glyph, 'line_color')
show(column(plot, picker))
More information can be found in the Reference for ColorPicker
.
DataTable¶
Bokeh provides a sophisticated data table widget based on SlickGrid. Note that since the table is configured with a data source object, any plots that share this data source will automatically have selections linked between the plot and the table (even in static HTML documents).
from datetime import date
from random import randint
from bokeh.io import show
from bokeh.models import ColumnDataSource, DataTable, DateFormatter, TableColumn
data = dict(
dates=[date(2014, 3, i+1) for i in range(10)],
downloads=[randint(0, 100) for i in range(10)],
)
source = ColumnDataSource(data)
columns = [
TableColumn(field="dates", title="Date", formatter=DateFormatter()),
TableColumn(field="downloads", title="Downloads"),
]
data_table = DataTable(source=source, columns=columns, width=400, height=280)
show(data_table)
More information can be found in the Reference for DataTable
.
DatePicker¶
A widget to allow the user to specify a date value.
from bokeh.io import show
from bokeh.models import CustomJS, DatePicker
date_picker = DatePicker(title='Select date', value="2019-09-20", min_date="2019-08-01", max_date="2019-10-30")
date_picker.js_on_change("value", CustomJS(code="""
console.log('date_picker: value=' + this.value, this.toString())
"""))
show(date_picker)
More information can be found in the Reference for DatePicker
.
DateRangeSlider¶
The Bokeh date range-slider can be configured with start
and end
date
values, a step
size, an initial value
, and a title
:
from datetime import date
from bokeh.io import show
from bokeh.models import CustomJS, DateRangeSlider
date_range_slider = DateRangeSlider(value=(date(2016, 1, 1), date(2016, 12, 31)),
start=date(2015, 1, 1), end=date(2017, 12, 31))
date_range_slider.js_on_change("value", CustomJS(code="""
console.log('date_range_slider: value=' + this.value, this.toString())
"""))
show(date_range_slider)
More information can be found in the Reference for DateRangeSlider
.
Div¶
A widget for displaying text that can support HTML in a <div> tag:
from bokeh.io import show
from bokeh.models import Div
div = Div(text="""Your <a href="https://en.wikipedia.org/wiki/HTML">HTML</a>-supported text is initialized with the <b>text</b> argument. The
remaining div arguments are <b>width</b> and <b>height</b>. For this example, those values
are <i>200</i> and <i>100</i>, respectively.""",
width=200, height=100)
show(div)
More information can be found in the Reference for Div
.
Dropdown¶
A button that displays a drop-down list of mutually exclusive items when clicked.
from bokeh.io import show
from bokeh.models import CustomJS, Dropdown
menu = [("Item 1", "item_1"), ("Item 2", "item_2"), None, ("Item 3", "item_3")]
dropdown = Dropdown(label="Dropdown button", button_type="warning", menu=menu)
dropdown.js_on_event("menu_item_click", CustomJS(code="console.log('dropdown: ' + this.item, this.toString())"))
show(dropdown)
More information can be found in the Reference for Dropdown
.
FileInput¶
A widget allowing users to choose a file and store its contents.
from bokeh.io import show
from bokeh.models import FileInput
file_input = FileInput()
show(file_input)
More information can be found in the Reference for FileInput
.
MultiChoice¶
A multi-select widget to present multiple available options in a compact horizontal layout:
from bokeh.io import show
from bokeh.models import CustomJS, MultiChoice
OPTIONS = ["foo", "bar", "baz", "quux"]
multi_choice = MultiChoice(value=["foo", "baz"], options=OPTIONS)
multi_choice.js_on_change("value", CustomJS(code="""
console.log('multi_choice: value=' + this.value, this.toString())
"""))
show(multi_choice)
More information can be found in the Reference for MultiChoice
.
MultiSelect¶
A multi-select widget to present multiple available options in vertical list:
from bokeh.io import show
from bokeh.models import CustomJS, MultiSelect
OPTIONS = [("1", "foo"), ("2", "bar"), ("3", "baz"), ("4", "quux")]
multi_select = MultiSelect(value=["1", "2"], options=OPTIONS)
multi_select.js_on_change("value", CustomJS(code="""
console.log('multi_select: value=' + this.value, this.toString())
"""))
show(multi_select)
More information can be found in the Reference for MultiSelect
.
Paragraph¶
A widget for displaying a block of text in an HTML <p> tag:
from bokeh.io import show
from bokeh.models import Paragraph
p = Paragraph(text="""Your text is initialized with the 'text' argument. The
remaining Paragraph arguments are 'width' and 'height'. For this example, those values
are 200 and 100, respectively.""",
width=200, height=100)
show(p)
More information can be found in the Reference for Paragraph
.
PasswordInput¶
A text input that obscures the entered text:
from bokeh.io import show
from bokeh.models import CustomJS, PasswordInput
password_input = PasswordInput(placeholder="enter password...")
password_input.js_on_change("value", CustomJS(code="""
console.log('password_input: value=' + this.value, this.toString())
"""))
show(password_input)
More information can be found in the Reference for PasswordInput
.
PreText¶
A widget for displaying a block of pre-formatted text in an HTML <pre> tag:
from bokeh.io import show
from bokeh.models import PreText
pre = PreText(text="""Your text is initialized with the 'text' argument.
The remaining Paragraph arguments are 'width' and 'height'. For this example,
those values are 500 and 100, respectively.""",
width=500, height=100)
show(pre)
More information can be found in the Reference for PreText
.
RadioButtonGroup¶
A radio button group can have at most one selected button at a time:
from bokeh.io import show
from bokeh.models import CustomJS, RadioButtonGroup
LABELS = ["Option 1", "Option 2", "Option 3"]
radio_button_group = RadioButtonGroup(labels=LABELS, active=0)
radio_button_group.js_on_click(CustomJS(code="""
console.log('radio_button_group: active=' + this.active, this.toString())
"""))
show(radio_button_group)
More information can be found in the Reference for RadioButtonGroup
.
RadioGroup¶
A radio group uses standard radio button appearance:
from bokeh.io import show
from bokeh.models import CustomJS, RadioGroup
LABELS = ["Option 1", "Option 2", "Option 3"]
radio_group = RadioGroup(labels=LABELS, active=0)
radio_group.js_on_click(CustomJS(code="""
console.log('radio_group: active=' + this.active, this.toString())
"""))
show(radio_group)
More information can be found in the Reference for RadioGroup
.
RangeSlider¶
The Bokeh range-slider can be configured with start
and end
values, a step
size,
an initial value
, and a title
:
from bokeh.io import show
from bokeh.models import CustomJS, RangeSlider
range_slider = RangeSlider(start=0, end=10, value=(1,9), step=.1, title="Stuff")
range_slider.js_on_change("value", CustomJS(code="""
console.log('range_slider: value=' + this.value, this.toString())
"""))
show(range_slider)
More information can be found in the Reference for RangeSlider
.
Select¶
A single selection widget:
from bokeh.io import show
from bokeh.models import CustomJS, Select
select = Select(title="Option:", value="foo", options=["foo", "bar", "baz", "quux"])
select.js_on_change("value", CustomJS(code="""
console.log('select: value=' + this.value, this.toString())
"""))
show(select)
More information can be found in the Reference for Select
.
Slider¶
The Bokeh slider can be configured with start
and end
values, a step
size,
an initial value
, and a title
:
from bokeh.io import show
from bokeh.models import CustomJS, Slider
slider = Slider(start=0, end=10, value=1, step=.1, title="Stuff")
slider.js_on_change("value", CustomJS(code="""
console.log('slider: value=' + this.value, this.toString())
"""))
show(slider)
More information can be found in the Reference for Slider
.
Spinner¶
A numeric spinner widget:
import numpy as np
from bokeh.io import show
from bokeh.layouts import column, row
from bokeh.models import Spinner
from bokeh.plotting import figure
x = np.random.rand(10)
y = np.random.rand(10)
p = figure(x_range=(0, 1), y_range=(0, 1))
points = p.scatter(x=x, y=y, size=4)
spinner = Spinner(title="Glyph size", low=1, high=40, step=0.5, value=4, width=80)
spinner.js_link('value', points.glyph, 'size')
show(row(column(spinner, width=100), p))
More information can be found in the Reference for Spinner
.
Tabs¶
Tab panes allow multiple plots or layouts to be shown in selectable tabs:
from bokeh.io import show
from bokeh.models import Panel, Tabs
from bokeh.plotting import figure
p1 = figure(width=300, height=300)
p1.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20, color="navy", alpha=0.5)
tab1 = Panel(child=p1, title="circle")
p2 = figure(width=300, height=300)
p2.line([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], line_width=3, color="navy", alpha=0.5)
tab2 = Panel(child=p2, title="line")
show(Tabs(tabs=[tab1, tab2]))
More information can be found in the Reference for Tabs
.
TextAreaInput¶
A widget for collecting multiple lines of text from a user:
from bokeh.io import show
from bokeh.models import CustomJS, TextAreaInput
text_area_input = TextAreaInput(value="default", rows=6, title="Label:")
text_area_input.js_on_change("value", CustomJS(code="""
console.log('text_area_input: value=' + this.value, this.toString())
"""))
show(text_area_input)
More information can be found in the Reference for TextAreaInput
.
TextInput¶
A widget for collecting a line of text from a user:
from bokeh.io import show
from bokeh.models import CustomJS, TextInput
text_input = TextInput(value="default", title="Label:")
text_input.js_on_change("value", CustomJS(code="""
console.log('text_input: value=' + this.value, this.toString())
"""))
show(text_input)
More information can be found in the Reference for TextInput
.
Toggle¶
The toggle button holds an on/off state:
from bokeh.io import show
from bokeh.models import CustomJS, Toggle
toggle = Toggle(label="Foo", button_type="success")
toggle.js_on_click(CustomJS(code="""
console.log('toggle: active=' + this.active, this.toString())
"""))
show(toggle)
More information can be found in the Reference for Toggle
.