diff --git a/examples/reference/widgets/Tabulator.ipynb b/examples/reference/widgets/Tabulator.ipynb index 3619b7aae0..92bdae5926 100644 --- a/examples/reference/widgets/Tabulator.ipynb +++ b/examples/reference/widgets/Tabulator.ipynb @@ -82,6 +82,11 @@ "* **``current_view``** (``DataFrame``): The current view of the table that is displayed, i.e. after sorting and filtering are applied\n", "* **``selected_dataframe``** (``DataFrame``): A DataFrame reflecting the currently selected rows.\n", "\n", + "##### Callbacks\n", + "\n", + "* **``on_click``**: Allows registering callbacks which are given `CellClickEvent` objects containing the `column`, `row` and `value` of the clicked cell.\n", + "* **``on_edit``**: Allows registering callbacks which are given `TableEditEvent` objects containing the `column`, `row`, `value` and `old` value.\n", + "\n", "___" ] }, @@ -559,6 +564,27 @@ "pn.widgets.Tabulator(sel_df, selectable_rows=lambda df: list(range(0, len(df), 2)))" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To trigger events based on an exact cell that was clicked you may also register an `on_click` callback which is called whenever a cell is clicked." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def click(event):\n", + " print(f'Clicked cell in {event.column} column, row {event.row}')\n", + "\n", + "select_table.on_click(click) \n", + "# Optionally we can also limit the callback to a specific column\n", + "# select_table.on_click(click, column='A') " + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -1064,7 +1090,7 @@ "source": [ "## Buttons\n", "\n", - "If you want to trigger custom actions by clicking on a table cell you may declare a set of `buttons` that are rendered in columns after all the data columns. To respond to button clicks you can register a callback using the `on_button_click` method:" + "If you want to trigger custom actions by clicking on a table cell you may declare a set of `buttons` that are rendered in columns after all the data columns. To respond to button clicks you can register a callback using the general `on_click` method:" ] }, { diff --git a/panel/models/tabulator.py b/panel/models/tabulator.py index 2ac42b82c6..2c32c0c098 100644 --- a/panel/models/tabulator.py +++ b/panel/models/tabulator.py @@ -42,9 +42,10 @@ class CellClickEvent(ModelEvent): event_name = 'cell-click' - def __init__(self, model, column, row): + def __init__(self, model, column, row, value=None): self.column = column self.row = row + self.value = value super().__init__(model=model) diff --git a/panel/models/tabulator.ts b/panel/models/tabulator.ts index f1fde5472d..56bb3ee50b 100644 --- a/panel/models/tabulator.ts +++ b/panel/models/tabulator.ts @@ -735,6 +735,10 @@ export class DataTabulatorView extends PanelHTMLBoxView { tab_column.headerFilterParams = tab_column.editorParams } } + tab_column.cellClick = (_: any, cell: any) => { + const index = cell._cell.row.data._index; + this.model.trigger_event(new CellClickEvent(column.field, index)) + } if (config_columns == null) columns.push(tab_column) } diff --git a/panel/widgets/tables.py b/panel/widgets/tables.py index 323f46206f..96594ee083 100644 --- a/panel/widgets/tables.py +++ b/panel/widgets/tables.py @@ -958,16 +958,14 @@ def _cleanup(self, root): super()._cleanup(root) def _process_event(self, event): + if self.pagination == 'remote': + nrows = self.page_size + event.row = (self.page-1)*nrows + if event.column not in self.buttons: + event.value = self._processed[event.column].iloc[event.row] if event.event_name == 'table-edit': - if self.pagination: - nrows = self.page_size - offset = (self.page-1)*nrows - else: - offset = 0 - row = offset + event.row if self._old is not None: - event.old = self._old[event.column].iloc[row] - event.value = self._processed[event.column].iloc[row] + event.old = self._old[event.column].iloc[event.row] for cb in self._on_edit_callbacks: cb(event) else: @@ -1543,6 +1541,24 @@ def on_edit(self, callback): """ self._on_edit_callbacks.append(callback) + def on_click(self, callback, column=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. + """ + if column not in self._on_click_callbacks: + self._on_click_callbacks[column] = [] + self._on_click_callbacks[column].append(callback) + def on_button_click(self, callback, column=None): """ Register a callback to be executed when a cell corresponding @@ -1558,6 +1574,11 @@ def on_button_click(self, callback, column=None): Optional argument restricting the callback to a specific column. """ + self.param.warning( + "DeprecationWarning: The on_button_click callbacks will be " + "removed before the 0.13.0 release, please use the generic " + "on_click callback instead." + ) if column not in self._on_click_callbacks: self._on_click_callbacks[column] = [] self._on_click_callbacks[column].append(callback)