Use TextInput as a filter on a 'string column'

I have displayed data in a DataTable and want to filter its content with a TextInput widget, similar to TextInput Example.

I tried it with a combination of BooleanFilter and CDSView:

import random
import string
import pandas as pd

from bokeh.io import show
from bokeh.models import TextInput, ColumnDataSource, CustomJS, Column, BooleanFilter, CDSView, TableColumn,\
    DataTable


def random_str():
    return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(20))


data = dict(options=[random_str() for _ in range(500)])
df = pd.DataFrame(data=data)
source = ColumnDataSource(data=data)

text_filter = BooleanFilter(booleans=[True] * df.shape[0])
view = CDSView(filter=text_filter)

columns = []
for col in list(df.columns):
    columns.append(TableColumn(field=col, title=col))
data_table = DataTable(source=source, columns=columns, height=500, width=300, view=view)

# Setting initial values
text_input = TextInput(value="", title="Enter filter")
callback = CustomJS(args=dict(source=source, text_filter=text_filter),
                    code="""
    text_filter.booleans = Array.from(source.data['options']).map(t => t.includes(cb_obj.value));
""")
text_input.js_on_change("value", callback)

show(Column(text_input, data_table))

I hoped that it would show only those rows including text written in the widget after pressing Enter, but nothing happens. What can I change to get this to work? Thank you in advance.

Bokeh version: 3.1.1.

oh my, I cannot believe I forgot this inside the callback:

source.change.emit();

With it everything is fine.

1 Like

It probably ought to work without as well, but I guess some internal plumbing is not hooked all the way up. But your solution is a good catch-all option in any case.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.