Update tabulator filter

Hi

I am trying to update filter by a button click. But not too sure how to make it works.

Any suggestion would be greatful.
Kind regards
Victor

import panel as pn
pn.extension('tabulator')
import pandas as pd

df = pd.DataFrame({
    'float': [3.14, 6.28, 9.42],
    'str': ['A', 'B', 'C'],
    'bool': [True, False, True],
}, index=[1, 2, 3])



tabulator_editors = {
    'float': {'type': 'number', 'max': 10, 'step': 0.1},
    'bool': {'type': 'tickCross', 'tristate': True, 'indeterminateValue': None},
    'str': {'type': 'list', 'valuesLookup': True}
}

header_filter_table = pn.widgets.Tabulator(
    df[['float', 'bool', 'str']], height=140, width=400, layout='fit_columns',
    editors=tabulator_editors, header_filters=True
)


button= pn.widgets.Button(
    name = 'add'
)

def filter_click(event):
    
    name = 'str'
    value = 'A'
    
    filters = header_filter_table.filters
    filters.append({'field': name, 'type': 'like', 'value': value})
    header_filter_table.filters = filters

button.on_click(filter_click)


pn.Column(
    button,
    header_filter_table
)

Victor,

One part of the problem seems to be that if you simply append an existing .filters list, panel likely is not picking up the change (it doesn’t trigger a param watcher).
That part you can test by changing the code to try to add an invalid filter syntax (scalar instead of dict):

This should create an exception but doesn’t:

def filter_click(event):
    
    name = 'str'
    value = 'A'
    
    filters = header_filter_table.filters
    
    # test1 - should trigger an error but doesn't
    filters.append('A')

    header_filter_table.filters = ['A']

This triggers an exception as expected (indicating that panel processes the .filters change). The traceback also gives you an idea what’s going on.

def filter_click(event):
    
    name = 'str'
    value = 'A'
    
    filters = header_filter_table.filters
    
    # test2 - triggers the watcher (panel picks up the change)  
    # (and results in an exception because it excepts a dict, not a scalar)
    header_filter_table.filters = ['A']

Why the table in my test still doesn’t filter down, even if you push a completely new dict with your custom filter, I don’t really know. Maybe there is a reason there are dedicated .add_filter()/remove_filter methods

Johann

1 Like

Victor,

Mixed news - I ran another quick test with explicitly triggering the watcher for the header_filter_table.value that contains the df. Doing that triggers panel to filter the df with your updated filter and the widget displays the filtered df (but not showing the ‘A’ value in the header-filter row field).

So your example will mostly work with the change below, but I’m unsure if what your’re trying to do is actually supported. The panel documentation seems to imply that the .filters attribute is to READ back any user-applied HEADER filters on the client side (after enabling/configuring HEADER-Filters at setup via the .header_filters). So it may not support update/overwrite User-set Header Filters on the client site at all.

You can push additional STANDARD filters via the .add_filters() method (eg. header_filter.tables.add_filters(‘A’, ‘str’) , but that does an exact match, not a LIKE match like the Header-filter does for a string.

def filter_click(event):
    
    name = 'str'
    value = 'A'
    
    filters = header_filter_table.filters
    print(filters)
    filters.append({'field': name, 'type': 'like', 'value': value})
   
    # trigger panel to filter the df with the updated filter and push out
    # (may be just a workaround for a bug or may be completely unsupported)
    header_filter_table.param.trigger('value')

regards,

Johann

1 Like

Hi Johann

Really thanks for you reply. That do works.

The only regret is we still can no see the filter item on the clint side filter
image

Except that. The trigger method is amazing. Thank for that

Kind regards
Victor

1 Like