Remove rows from Tabulator widget

Hi all,
I’m using panel.widget.Tabulator for the first time. It’s super useful widget and very versatile.
I wish there was more documents and examples for it.
I need to add a trash can column to the table and allow user to delete a row when they click on the trash can for that row.
Getting idea from here, I wrote following code:

# https://discourse.holoviz.org/t/catch-cellclick-event-in-table/3544/2
import panel as pn
import pandas as pd

pn.extension("tabulator")

df = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]], columns=['a', 'b', 'c'])
tbl = pn.widgets.Tabulator(df, selectable=True, buttons={"Trash": "<i class='fa fa-trash'></i>"}, disabled=True,)
 
def update_selection(event):
    tbl.value=tbl.value.iloc[list(set(tbl.value.index)-set(tbl.selection))]
    return event

update_selection=pn.bind(update_selection, tbl.param.selection)

pn.Column(tbl, update_selection).servable()
  1. When user clicks anywhere in a row, that row will be selected. I need to restrict that to clicking on the trash can only.
  2. When user clicks a.k.a selects the row, it will be removed from tbl.value but the table will show as before
    image

What am I missing?
Any tip is appreciated.

I found following in the documents, but I still cannot get it working.

| on_click(self, callback: ‘Callable[[CellClickEvent], None]’, column: ‘Optional[str]’ = None)
| Register a callback to be executed when any cell is clicked.
| The callback is given a CellClickEvent declaring the column
| and row of the cell that was clicked.
|

Arguments
callback: (callable)
The callback to run on edit events.
column: (str)
Optional argument restricting the callback to a specific
column.
  1. I think the first issue can be resolved by passing column=‘Trash’ to on_click()

With a little bit of hacking, I made it work:

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

df = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]], columns=['a', 'b', 'c'])
tbl = pn.widgets.Tabulator(df.copy(), selectable=True, buttons={"Trash": "<i class='fa fa-trash'></i>"}, disabled=True)
 
def delete_selected_row(event):
    tbl.value=tbl.value.drop(tbl.selection, inplace=False) 
    tbl.value.reset_index(inplace=True, drop=True)
    tbl.value=tbl.value.iloc[:]
    return 

tbl.on_click(delete_selected_row, column='Trash') 

pn.Column(tbl).servable()
1 Like

Thanks for the solution, Mana. Works for me too!

Any way we can have below 3 functionalities?

  1. What you showed about deleting a row
  2. Adding a row
  3. Editing a cell in a row/column

I am quite new to Panel so learning along the way!

Hi Nik,
I’m glad it helped.

  1. The solution is above.
  2. I believe you can patch the tabulator with new dataset.
  3. I think by default you can edit cells. You can turn it off though.

You may find following helpful:

import holoviews as hv
import panel as pn
hv.help(pn.widgets.Tabulator)

Thanks Mana. I have been following the Tabulator documentation, will look more into that.
Regarding point 3, yes, that is true. Just with the above solution, it is not possible to edit the table as the whole row is selected for deletion. If there is a workaround, please share, else I will figure it out. Thanks in advance!

Ah got it. I had to set “disabled=False” in tbl = pn.widgets.Tabulator() call. So now both editing and removing a row works!
I will figure out how to add a row dynamically to an existing table (just like you did to remove a row).

1 Like

I just saw your follow up question. I’m glad you figured it out.

Very nice solution. There’s one little limitation that can easily be fixed. If you click directly on the trash icon (without highlighting the row) nothing happens. This can be fixed by changing the function slightly as follows:

def delete_selected_row(event):
        tbl.value=tbl.value.drop(event.row) 
    return 
1 Like