1616
1717from importlib import resources
1818import functools
19+ import logging
1920import math
20- from typing import Any , Dict , Iterator , List , Optional , Type
21+ from typing import Any , Dict , Iterator , List , Optional , Tuple , Type
2122import uuid
2223
2324import pandas as pd
@@ -57,6 +58,8 @@ class TableWidget(WIDGET_BASE):
5758 page_size = traitlets .Int (0 ).tag (sync = True )
5859 row_count = traitlets .Int (0 ).tag (sync = True )
5960 table_html = traitlets .Unicode ().tag (sync = True )
61+ sort_column = traitlets .Unicode ("" ).tag (sync = True )
62+ sort_ascending = traitlets .Bool (True ).tag (sync = True )
6063 _initial_load_complete = traitlets .Bool (False ).tag (sync = True )
6164 _batches : Optional [blocks .PandasBatches ] = None
6265 _error_message = traitlets .Unicode (allow_none = True , default_value = None ).tag (
@@ -83,6 +86,7 @@ def __init__(self, dataframe: bigframes.dataframe.DataFrame):
8386 self ._all_data_loaded = False
8487 self ._batch_iter : Optional [Iterator [pd .DataFrame ]] = None
8588 self ._cached_batches : List [pd .DataFrame ] = []
89+ self ._last_sort_state : Optional [Tuple [str , bool ]] = None
8690
8791 # respect display options for initial page size
8892 initial_page_size = bigframes .options .display .max_rows
@@ -215,6 +219,27 @@ def _set_table_html(self) -> None:
215219 )
216220 return
217221
222+ # Apply sorting if a column is selected
223+ df_to_display = self ._dataframe
224+ if self .sort_column :
225+ try :
226+ df_to_display = df_to_display .sort_values (
227+ by = self .sort_column , ascending = self .sort_ascending
228+ )
229+ except KeyError :
230+ logging .warning (
231+ f"Attempted to sort by unknown column: { self .sort_column } "
232+ )
233+
234+ # Reset batches when sorting changes
235+ if self ._last_sort_state != (self .sort_column , self .sort_ascending ):
236+ self ._batches = df_to_display ._to_pandas_batches (page_size = self .page_size )
237+ self ._cached_batches = []
238+ self ._batch_iter = None
239+ self ._all_data_loaded = False
240+ self ._last_sort_state = (self .sort_column , self .sort_ascending )
241+ self .page = 0 # Reset to first page
242+
218243 start = self .page * self .page_size
219244 end = start + self .page_size
220245
@@ -235,6 +260,11 @@ def _set_table_html(self) -> None:
235260 table_id = f"table-{ self ._table_id } " ,
236261 )
237262
263+ @traitlets .observe ("sort_column" , "sort_ascending" )
264+ def _sort_changed (self , _change : Dict [str , Any ]):
265+ """Handler for when sorting parameters change from the frontend."""
266+ self ._set_table_html ()
267+
238268 @traitlets .observe ("page" )
239269 def _page_changed (self , _change : Dict [str , Any ]) -> None :
240270 """Handler for when the page number is changed from the frontend."""
0 commit comments