diff --git a/nicegui_tabulator/core/tabulator.js b/nicegui_tabulator/core/tabulator.js index 1a1e190..eb78abe 100644 --- a/nicegui_tabulator/core/tabulator.js +++ b/nicegui_tabulator/core/tabulator.js @@ -115,7 +115,8 @@ export default { name = name.slice(1); args = args.map((arg) => new Function(`return (${arg})`)()); } - return runMethod(this.table, name, args); + const result = runMethod(this.table, name, args); + return result instanceof Promise ? null : result; }, setColumns(columns) { diff --git a/nicegui_tabulator/core/tabulator.py b/nicegui_tabulator/core/tabulator.py index 7786968..a68cc9d 100644 --- a/nicegui_tabulator/core/tabulator.py +++ b/nicegui_tabulator/core/tabulator.py @@ -155,7 +155,7 @@ def set_columns(self, columns: List[Dict]) -> None: @self.__deferred_task.register def _(): - self.run_method("setColumns", columns) + return self.run_method("setColumns", columns) def update_column_definition(self, field: str, definition: Dict) -> None: """ @@ -206,7 +206,7 @@ def add_column( @self.__deferred_task.register def _(): - self.run_table_method("addColumn", definition, before, position) + return self.run_table_method("addColumn", definition, before, position) @classmethod def from_pandas( @@ -366,10 +366,9 @@ def set_data( """ self._set_data_on_server(data) - self.run_table_method( + return self.run_table_method( "setData", data, timeout=timeout, check_interval=check_interval ) - return self def replace_data(self, data: List[Dict]): """replace the data of the table. @@ -380,8 +379,7 @@ def replace_data(self, data: List[Dict]): data (List[Dict]): The data to replace the current data with. """ - self.set_data(data) - return self + return self.set_data(data) def update_data( self, data: List[Dict], *, timeout: float = 1, check_interval: float = 0.01 @@ -397,10 +395,9 @@ def update_data( """ self._update_data_on_server(data) - self.run_table_method( + return self.run_table_method( "updateData", data, timeout=timeout, check_interval=check_interval ) - return self def add_data( self, @@ -424,7 +421,7 @@ def add_data( """ self._add_data_on_server(data, at_top, index) - self.run_table_method( + return self.run_table_method( "addData", data, at_top, @@ -432,7 +429,6 @@ def add_data( timeout=timeout, check_interval=check_interval, ) - return self def update_or_add_data( self, data: List[Dict], *, timeout: float = 1, check_interval: float = 0.01 @@ -449,10 +445,9 @@ def update_or_add_data( """ self._update_or_add_data_on_server(data) - self.run_table_method( + return self.run_table_method( "updateOrAddData", data, timeout=timeout, check_interval=check_interval ) - return self def clear_data(self, *, timeout: float = 1, check_interval: float = 0.01): """clear the data of the table. @@ -465,18 +460,16 @@ def clear_data(self, *, timeout: float = 1, check_interval: float = 0.01): """ self._set_data_on_server([]) - self.run_table_method( + return self.run_table_method( "clearData", timeout=timeout, check_interval=check_interval ) - return self def sync_data_to_client(self): """sync server data to the client. @see https://github.com/CrystalWindSnake/nicegui-tabulator/tree/main?tab=readme-ov-file##cell-slot """ - self.set_data(self._props["options"]["data"]) - return self + return self.set_data(self._props["options"]["data"]) def _add_data_on_server( self, @@ -548,7 +541,7 @@ def print( config (Optional[Dict], optional): An object that can be used to override the object set on the printConfig option. Defaults to None. """ self.sync_data_to_client() - self.run_table_method("print", row_range_lookup, style, config) + return self.run_table_method("print", row_range_lookup, style, config) async def get_selected_data( self, *, timeout: float = 1, check_interval: float = 0.01 diff --git a/nicegui_tabulator/core/utils.py b/nicegui_tabulator/core/utils.py index 6abefff..74f2504 100644 --- a/nicegui_tabulator/core/utils.py +++ b/nicegui_tabulator/core/utils.py @@ -1,11 +1,15 @@ -from typing import Callable +from typing import Union, Callable from nicegui import ui, Client as ng_client +from nicegui.awaitable_response import AwaitableResponse +import asyncio import uuid +_TTask = Union[Callable[..., None], Callable[..., AwaitableResponse]] + class DeferredTask: def __init__(self): - self._tasks = [] + self._tasks: list[_TTask] = [] self.component_connected = False async def on_client_connect( @@ -17,7 +21,7 @@ async def on_client_connect( ui.context.client.on_connect(on_client_connect) - def register(self, task: Callable[..., None]): + def register(self, task: _TTask): if ui.context.client.has_socket_connection and self.component_connected: task() else: @@ -25,10 +29,15 @@ def register(self, task: Callable[..., None]): def flush(self): for task in self._tasks: - task() + self._execute_task(task) self._tasks.clear() + def _execute_task(self, task): + result = task() + if asyncio.iscoroutine(result): + asyncio.create_task(result) + def generate_dataframe_unique_id_column_name(): return f"__{uuid.uuid4().hex}" diff --git a/tests/test_tabulator.py b/tests/test_tabulator.py index 5bd3864..ab78034 100644 --- a/tests/test_tabulator.py +++ b/tests/test_tabulator.py @@ -79,7 +79,7 @@ def expect_server_data(self, page: Page): server = page.locator(f".{self.server_classes}") client = page.locator(f".{self.client_classes}") page.locator(f".{self.show_client_data_btn_class}").click() - expect(server).to_contain_text(client.inner_text()) + expect(client).to_contain_text(server.inner_text()) def test_base(browser: BrowserManager, page_path: str): @@ -682,24 +682,26 @@ def _(): label_server_data = server_data_checker.create_elements(table) + async def add_data_at_top(): + await table.add_data( + [{"id": 3, "name": "new-bar1", "age": "99"}], at_top=True + ) + label_server_data.set_text(str(table.data)) + + async def add_data_at_bottom(): + await table.add_data( + [{"id": 4, "name": "new-bar2", "age": "99"}], at_top=False + ) + label_server_data.set_text(str(table.data)) + ui.button( "add data at top", - on_click=lambda: ( - table.add_data( - [{"id": 3, "name": "new-bar1", "age": "99"}], at_top=True - ), - label_server_data.set_text(str(table.data)), - ), + on_click=add_data_at_top, ).classes("at-top") ui.button( "add data at bottom", - on_click=lambda: ( - table.add_data( - [{"id": 4, "name": "new-bar2", "age": "99"}], at_top=False - ), - label_server_data.set_text(str(table.data)), - ), + on_click=add_data_at_bottom, ).classes("at-bottom") page = browser.open(page_path) @@ -723,6 +725,7 @@ def _(): ], ) + # page.pause() server_data_checker.expect_server_data(page)