Widgets and DOM elements#
Widgets are interactive control and display elements that can be added to Bokeh documents to provide a front end user interface to a visualization. Widgets can be added directly to the document root or be nested inside a layout.
Bokeh’s widgets offer a range of interactive features that you can use to drive new computations, update plots, and connect to other programmatic functionality.
Bokeh provides a simple default set of widgets. You can create your own custom widgets, or wrap different third party widget libraries by creating custom extensions as described in Custom extensions.
Widget interactivity#
While some widgets are only meant to display data, others can be used to interactively manipulate data and properties of objects in your visualization.
Bokeh uses callbacks to handle these interactions. There are two types of callbacks:
Which one to use depends on whether you are using Bokeh server or are generating standalone HTML output:
If you want to use widgets to interact with Bokeh objects in a standalone HTML document, the browser needs to handle all interactivity. Therefore, you can only use JavaScript callbacks. You can write your own Javascript code, or use Bokeh’s pre-defined Python conveniences such as the js_link function or a
SetValue
object which generate the necessary JavaScript code for you.If you want to use widgets in connection with a Bokeh server, the server can handle some interactivity. This allows you to use callbacks written in Python. Additionally, since the visualization itself is displayed in a browser, you still can use JavaScript callbacks as well!
Widget tooltips#
You can attach tooltips to widgets. This can be helpful to provide additional information about the widget’s purpose or use, for example.
Hover over the question mark icon next to “Choose values” to see the tooltip.
See UI elements supporting tooltips for more information about adding tooltips to widgets.
Bokeh’s built-in widgets#
The sections below are examples for all widgets available in Bokeh. Many of the examples produce print output using the JavaScript console.log function. You can see this output in your browser’s JavaScript console log.
AutocompleteInput#
The AutocompleteInput widget is a general-purpose text input widget that uses a list of possible inputs to provide autocomplete while typing.
from bokeh.io import show
from bokeh.models import AutocompleteInput
from bokeh.sampledata.world_cities import data
completion_list = data.dropna()["name"].tolist()
auto_complete_input = AutocompleteInput(title="Enter a city:", completions=completion_list)
show(auto_complete_input)
More information about buttons can be found in the reference guide entry for
AutocompleteInput
.
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_change('active', CustomJS(code="""
console.log('checkbox_group: active=' + this.active, this.toString())
"""))
show(checkbox_group)
More information can be found in the reference guide entry for CheckboxGroup
.
ColorPicker#
A widget to allow the user to specify an RGB color value.
from bokeh.layouts import column
from bokeh.models import ColorPicker
from bokeh.plotting import figure, show
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 guide entry for ColorPicker
.
DataCube#
Bokeh provides a data cube widget based capable of aggregating hierarchical data. Note that since the data cube 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 bokeh.io import show
from bokeh.models import (ColumnDataSource, DataCube, GroupingInfo,
StringFormatter, SumAggregator, TableColumn)
source = ColumnDataSource(data=dict(
d0=['A', 'E', 'E', 'E', 'J', 'L', 'M'],
d1=['B', 'D', 'D', 'H', 'K', 'L', 'N'],
d2=['C', 'F', 'G', 'H', 'K', 'L', 'O'],
px=[10, 20, 30, 40, 50, 60, 70],
))
target = ColumnDataSource(data=dict(row_indices=[], labels=[]))
formatter = StringFormatter(font_style='bold')
columns = [
TableColumn(field='d2', title='Name', width=80, sortable=False, formatter=formatter),
TableColumn(field='px', title='Price', width=40, sortable=False),
]
grouping = [
GroupingInfo(getter='d0', aggregators=[SumAggregator(field_='px')]),
GroupingInfo(getter='d1', aggregators=[SumAggregator(field_='px')]),
]
cube = DataCube(source=source, columns=columns, grouping=grouping, target=target)
show(cube)
More information can be found in the reference guide entry for DataTable
.
DataTable#
Bokeh provides a sophisticated data table widget. 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 guide entry 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 guide entry for DatePicker
.
DateRangePicker#
A widget to allow the user to specify a range between two date values.
from bokeh.io import show
from bokeh.models import CustomJS, DateRangePicker
date_range_picker = DateRangePicker(
title="Select date range",
value=("2019-09-20", "2019-10-15"),
min_date="2019-08-01",
max_date="2019-10-30",
width=400,
)
date_range_picker.js_on_change("value", CustomJS(code="""
console.log("date_range_picker: value=" + this.value, this.toString())
"""))
show(date_range_picker)
More information can be found in the reference guide entry for DateRangePicker
.
MultipleDatePicker#
A widget to allow the user to specify multiple date values.
from bokeh.io import show
from bokeh.models import CustomJS, MultipleDatePicker
multiple_date_picker = MultipleDatePicker(
title="Select dates",
value=["2019-09-20", "2019-09-21", "2019-10-15"],
min_date="2019-08-01",
max_date="2019-10-30",
width=400,
)
multiple_date_picker.js_on_change("value", CustomJS(code="""
console.log("multiple_date_picker: value=" + this.value, this.toString())
"""))
show(multiple_date_picker)
More information can be found in the reference guide entry for MultipleDatePicker
.
DatetimePicker#
A widget to allow the user to specify a date and time value.
from bokeh.io import show
from bokeh.models import CustomJS, DatetimePicker
datetime_picker = DatetimePicker(
title="Select date and time",
value="2019-09-20T12:37:51",
min_date="2019-08-01T09:00:00",
max_date="2019-10-30T18:00:00",
)
datetime_picker.js_on_change("value", CustomJS(code="""
console.log("datetime_picker: value=" + this.value, this.toString())
"""))
show(datetime_picker)
More information can be found in the reference guide entry for DatetimePicker
.
DatetimeRangePicker#
A widget to allow the user to specify a range between two date and time values.
from bokeh.io import show
from bokeh.models import CustomJS, DatetimeRangePicker
datetime_range_picker = DatetimeRangePicker(
title="Select date and time range",
value=("2019-09-20T12:37:51", "2019-10-15T17:59:18"),
min_date="2019-08-01T09:00:00",
max_date="2019-10-30T18:00:00",
width=400,
)
datetime_range_picker.js_on_change("value", CustomJS(code="""
console.log("datetime_range_picker: value=" + this.value, this.toString())
"""))
show(datetime_range_picker)
More information can be found in the reference guide entry for DatetimeRangePicker
.
MultipleDatetimePicker#
A widget to allow the user to specify multiple date and time values.
from bokeh.io import show
from bokeh.models import CustomJS, MultipleDatetimePicker
multiple_datetime_picker = MultipleDatetimePicker(
title="Select dates and times",
value=[
"2019-09-20T12:59:31",
"2019-09-21T13:31:00",
"2019-10-15T14:00:18",
],
min_date="2019-08-01T09:00:00",
max_date="2019-10-30T18:00:00",
width=400,
)
multiple_datetime_picker.js_on_change("value", CustomJS(code="""
console.log("multiple_datetime_picker: value=" + this.value, this.toString())
"""))
show(multiple_datetime_picker)
More information can be found in the reference guide entry for MultipleDatetimePicker
.
TimePicker#
A widget to allow the user to specify a time value.
from bokeh.io import show
from bokeh.models import CustomJS, TimePicker
time_picker = TimePicker(title="Select time", value="12:59:31", min_time="09:00:00", max_time="18:00:00")
time_picker.js_on_change("value", CustomJS(code="""
console.log("time_picker: value=" + this.value, this.toString())
"""))
show(time_picker)
More information can be found in the reference guide entry for TimePicker
.
DateRangeSlider#
The Bokeh date range-slider can be configured with start
and end
date
values, a step
size in units of days, 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 guide entry for DateRangeSlider
.
DateSlider#
The Bokeh date slider can be configured with start
and end
date
values, a step
size in units of days, an initial value
, and a title
:
from datetime import date
from bokeh.io import show
from bokeh.models import CustomJS, DateSlider
date_slider = DateSlider(value=date(2016, 1, 1),
start=date(2015, 1, 1),
end=date(2017, 12, 31))
date_slider.js_on_change("value", CustomJS(code="""
console.log('date_slider: value=' + this.value, this.toString())
"""))
show(date_slider)
More information can be found in the reference guide entry for DateSlider
.
DatetimeRangeSlider#
The Bokeh datetime range slider is the same as the date range slider except that it uses datetimes that include hours, minutes and seconds:
from datetime import datetime
from bokeh.io import show
from bokeh.models import CustomJS, DatetimeRangeSlider
datetime_range_slider = DatetimeRangeSlider(value=(datetime(2022, 3, 8, 12), datetime(2022, 3, 25, 18)),
start=datetime(2022, 3, 1), end=datetime(2022, 3, 31))
datetime_range_slider.js_on_change("value", CustomJS(code="""
console.log('datetime_range_slider: value=' + this.value, this.toString())
"""))
show(datetime_range_slider)
More information can be found in the reference guide entry for DatetimeRangeSlider
.
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 guide entry 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)
Similar to the Button widget, the
dropdown button can also use an Icon
(such as
BuiltinIcon
, SVGIcon
, or
TablerIcon
).`
More information can be found in the reference guide entry 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 guide entry 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 guide entry 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 guide entry for MultiSelect
.
NumericInput#
A widget to allow the user to enter a numeric value.
from bokeh.io import show
from bokeh.models import NumericInput
numeric_input = NumericInput(value=1, low=1, high=10, title="Enter a number between 1 and 10:")
show(numeric_input)
More information can be found in the reference guide entry for NumericInput
.
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 guide entry 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 guide entry 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 guide entry for PreText
.
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_event('button_click', CustomJS(code="""
console.log('radio_group: active=' + this.origin.active, this.toString())
"""))
show(radio_group)
More information can be found in the reference guide entry 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 guide entry 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 guide entry 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 guide entry for Slider
.
Spinner#
A numeric spinner widget:
import numpy as np
from bokeh.layouts import column, row
from bokeh.models import Spinner
from bokeh.plotting import figure, show
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 guide entry for Spinner
.
Switch#
An on/off toggle switch:
from bokeh.io import show
from bokeh.models import CustomJS, Switch
switch = Switch(active=True)
switch.js_on_change("active", CustomJS(code="""
console.log('switch: active=' + this.active, this.toString())
"""))
show(switch)
More information can be found in the reference guide entry for Switch
.
Tabs#
Tab panes allow multiple plots or layouts to be shown in selectable tabs:
from bokeh.models import TabPanel, Tabs
from bokeh.plotting import figure, show
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 = TabPanel(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 = TabPanel(child=p2, title="line")
show(Tabs(tabs=[tab1, tab2]))
More information can be found in the reference guide entry 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 guide entry 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 guide entry 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_event('button_click', CustomJS(args=dict(btn=toggle), code="""
console.log('toggle: active=' + btn.active, this.toString())
"""))
show(toggle)
Like with a standard Button
widget, the toggle button can also use an Icon
(such as
BuiltinIcon
, SVGIcon
, or
TablerIcon
).`
More information can be found in the reference guide entry for Toggle
.