From bf60db8b97bd62c68717b5eb54d35f2d302ae3f2 Mon Sep 17 00:00:00 2001 From: maximlt Date: Mon, 8 Aug 2022 17:54:07 +0200 Subject: [PATCH 1/3] don't re-apply the front-end sorters on cell edits --- panel/models/tabulator.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/panel/models/tabulator.ts b/panel/models/tabulator.ts index 233cfe13ce..937f59f2d9 100644 --- a/panel/models/tabulator.ts +++ b/panel/models/tabulator.ts @@ -1106,7 +1106,6 @@ export class DataTabulatorView extends PanelHTMLBoxView { this._tabulator_cell_updating = false } this.model.trigger_event(new TableEditEvent(field, index)) - this.setSorters() this.tabulator.scrollToRow(index, "top", false) } } From c5d326ee2bf72a4d873a0a38f5811187c779da1d Mon Sep 17 00:00:00 2001 From: maximlt Date: Mon, 8 Aug 2022 17:54:17 +0200 Subject: [PATCH 2/3] add a test --- panel/tests/ui/widgets/test_tabulator.py | 41 ++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/panel/tests/ui/widgets/test_tabulator.py b/panel/tests/ui/widgets/test_tabulator.py index ae372f629c..97ee801678 100644 --- a/panel/tests/ui/widgets/test_tabulator.py +++ b/panel/tests/ui/widgets/test_tabulator.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import datetime as dt import time @@ -117,6 +119,16 @@ def count_per_page(count: int, page_size: int): return count_per_page +def tabulator_column_values(page, col_name: str) -> list[str]: + """Get the values of a column. + + >>> tabulator_column_values(page, 'color') + ['blue', 'red'] + """ + cells = page.locator(f'[tabulator-field={col_name}][role=gridcell]') + return cells.all_inner_texts() + + def test_tabulator_default(page, port, df_mixed, df_mixed_as_string): nrows, ncols = df_mixed.shape widget = Tabulator(df_mixed) @@ -2503,6 +2515,35 @@ def test_tabulator_sorters_pagination(page, port, df_mixed, pagination): wait_until(page, lambda: widget.current_view.equals(expected_sorted_df)) +def test_tabulator_edit_event_sorters_not_automatically_applied(page, port, df_mixed): + widget = Tabulator(df_mixed, sorters=[{'field': 'str', 'dir': 'desc'}]) + + values = [] + widget.on_edit(lambda e: values.append((e.column, e.row, e.old, e.value))) + + serve(widget, port=port, threaded=True, show=False) + + time.sleep(0.2) + + page.goto(f"http://localhost:{port}") + + expected_vals = list(df_mixed['str'].sort_values(ascending=False)) + + wait_until(page, lambda: tabulator_column_values(page, 'str') == expected_vals) + + # Chankge the cell that contains B to BB + cell = page.locator('text="B"') + cell.click() + editable_cell = page.locator('input[type="text"]') + editable_cell.fill("Z") + editable_cell.press('Enter') + + wait_until(page, lambda: len(values) == 1) + + expected_vals = [item if item != 'B' else 'Z' for item in expected_vals] + wait_until(page, lambda: tabulator_column_values(page, 'str') == expected_vals) + + @pytest.mark.xfail(reason='See https://github.com/holoviz/panel/issues/3660') def test_tabulator_edit_event_and_header_filters(page, port): df = pd.DataFrame({ From ed9b758e0304265d636faf4574fba414a8e62540 Mon Sep 17 00:00:00 2001 From: maximlt Date: Mon, 8 Aug 2022 17:58:56 +0200 Subject: [PATCH 3/3] update the docs --- examples/reference/widgets/Tabulator.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/reference/widgets/Tabulator.ipynb b/examples/reference/widgets/Tabulator.ipynb index 57be012e3e..ed6c580903 100644 --- a/examples/reference/widgets/Tabulator.ipynb +++ b/examples/reference/widgets/Tabulator.ipynb @@ -78,7 +78,7 @@ "\n", "##### Properties\n", "\n", - "* **``current_view``** (``DataFrame``): The current view of the table that is displayed, i.e. after sorting and filtering are applied\n", + "* **``current_view``** (``DataFrame``): The current view of the table that is displayed, i.e. after sorting and filtering are applied. `current_view` isn't guaranteed to be in sync with the displayed current view when sorters are applied and values are edited, in which case `current_view` is sorted while the displayed table isn't.\n", "* **``selected_dataframe``** (``DataFrame``): A DataFrame reflecting the currently selected rows.\n", "\n", "##### Callbacks\n",