Add reactivity to components#

This guide addresses how to bind Parameters and bound functions on components.

New in version 1.0.0: Bind Parameters, widgets and bound functions to component Parameters.


The power to binding Parameters, widgets and interactive functions to component Parameters can be used with all of Panel’s widgets and panes. This provides a powerful way to add interactivity to an application and update specific Parameters without writing callbacks.

Let’s start with an using existing components to give you an idea of the power behind this. In this example we bind the value of a slider widget to the page_size Parameter of the Tabulator widget. This will allow you to change the page size of the table with the slider:

import pandas as pd
import panel as pn

pn.extension("tabulator")

df = pd.read_csv("https://datasets.holoviz.org/penguins/v1/penguins.csv")

slider = pn.widgets.IntSlider(value=5, start=1, end=10, name='page_size')
tabulator = pn.widgets.Tabulator(df, page_size=slider, pagination="remote")

pn.Column(slider, tabulator)

Binding bound function on components#

Prerequisites

Read the How to > Make your functions interactive guide to learn how to bind functions.

Often times the value of a widget or Parameter will not map directly onto the Parameter you want to set. In these cases, you can write a reactive function (using pn.bind), which transforms the values of the inputs.

Let’s say we have a function that takes a string and a number as input:

def object_creator(string, number):
    return string * number

object_creator('🐘', 5)
🐘🐘🐘🐘🐘

Now we can bind IntSlider and the Select widgets to the object_creator to create an interactive string. Once we have a reactive function we can pass it to a component, e.g. Markdown to render this:

slider = pn.widgets.IntSlider(value=5, start=1, end=10)
select = pn.widgets.Select(value="⭐", options=["⭐", "🐘"])

iobject = pn.bind(object_creator, select, slider)

pn.Row(slider, select, pn.pane.Markdown(iobject))

This approach is preferred over rendering reactive functions directly because it is more efficient and updates only the specific Parameters that are being changed.

If you want to update multiple Parameters at the same time you can pass a reactive function (or Parameter) as the refs keyword argument. The function (or Parameter) must return a dictionary of parameters to update, e.g. let’s say you wanted to write a function that returns both

slider = pn.widgets.IntSlider(value=5, start=1, end=10, name='Number')
select = pn.widgets.RadioButtonGroup(value="⭐", options=["⭐", "🐘"], name='String', align='center')
size = pn.widgets.IntSlider(value=12, start=6, end=24, name='Size')

def refs(string, number, size):
    return {
        'object': string * number,
        'styles': {'font-size': f'{size}pt'}
    }

irefs = pn.bind(refs, select, slider, size)

pn.Row(slider, size, select, pn.pane.Markdown(refs=irefs))

In this way we can update both the current object and the styles Parameter of the Markdown pane simultaneously.