Bindings with Tabulator

Hi there,

I’m facing a strange behaviour of Panel (or maybe of me?).

After applying How to get columns of uploaded excel file?, I managed to bind my Tabulator table with a file upload widget. But after enhancing the code with a second bind, the bindings (neither the second nor the first) seem to work.

My page looks like this:

and aims to:

  • upload by default the project file ‘default.proj.json’ into Tabulator as a DataFrame
  • allow to upload a different project file with bound upload widget saved in filesystem
  • edit the Tabulator table and checking the input consistency against regex rules
  • save the changes inot the opened file (or default) with a button widget (for the time being it only prints the DataFrame)

As a result, the bindings do not seem to work since the alert states do not change and the ‘print’ does not happen.

My code is as follows (well I summarized it a bit for readability):

import io
import re
import panel as pn
import pandas as pd

(...)

def get_data1(file):
    if file is not None:
        alert1a.object = 'Loading file'
        df = pd.read_json(io.BytesIO(file))
        alert1a.object = 'File loaded'
        btn_save1.visible = True
        table1.value = df
        return df
    return pd.DataFrame()

upload1 = pn.widgets.FileInput(accept='.json', multiple=False)
if 'uploaded1' not in globals():
    uploaded1 = pd.read_json('./apps/default.proj.json', dtype='str')
else:
    uploaded1 = pn.bind(get_data1, file=upload1).rx() # extract a reactive df 

alert1a = pn.pane.Alert('Waiting for file upload', alert_type='light')

# TABLE section
def table1_changed(event):
    MASK = {'0':FLOAT_MASK,
            '1':COLOR_MASK,
            '2':FLOAT_MASK,
            '3':REGEX_MASK,
            '4':BOOL_MASK,
            '5':DIR_MASK,
            '6':REGEX_MASK,
            '7':LIST_MASK
            }
    if event.value != event.old:
        if re.findall(MASK[str(event.row)],event.value):
            alert1b.object = 'No error'
            alert1b.alert_type = 'light'
            btn_save1.visible = True
        else:
            alert1b.object = f'Format error @ row {event.row}. Project file cannot be saved.'
            alert1b.alert_type = 'warning'
            btn_save1.visible = False

alert1b = pn.pane.Alert('No error', alert_type='light')

table1 = pn.widgets.Tabulator(uploaded1,
                                width=1500,
                                height=720,
                                disabled=False,
                                layout='fit_data_fill',
                                sortable=True,
                                on_edit=lambda e: table1_changed(e),
                                pagination='remote',
                                stylesheets=[stylesheet],
                                header_filters=False,
                                page_size=25,
                                )

# SAVE btn section
def save_data1(bool, df):
    print(df)
    btn_save1.visible = False
    return
    
btn_save1 = pn.widgets.Button(name='Save', button_type='primary', visible=False)
table1_saved = pn.bind(save_data1, bool=btn_save1, df=table1)

tab1 = pn.GridSpec(sizing_mode='stretch_both')
tab1[0,:] = pn.pane.Markdown('## Project File to upload') # header line
tab1[1:15,0] = pn.Column(                                   # sidebar
                                        upload1,
                                        alert1a,
                            )
tab1[1:15,1:5] = pn.Column(                                 # body
                                        alert1b,
                                        btn_save1,
                                        table1,                                       
                            )

tabs = pn.Tabs(('Upload PF', tab1))

tabs.servable()

Sorry for such a long topic, but I have no clue what I’m missing here.