From de3a9f6f2a2d04ae2ff99e3119dd9ead20148f6b Mon Sep 17 00:00:00 2001 From: Alexandr Zarubkin Date: Mon, 16 Dec 2024 12:16:17 +0300 Subject: [PATCH 1/4] Implement multi-column row keys It is now possible to specify a list of keys as row-key property. --- nicegui/elements/table.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/nicegui/elements/table.py b/nicegui/elements/table.py index d478ad6d2..f7800a5cc 100644 --- a/nicegui/elements/table.py +++ b/nicegui/elements/table.py @@ -66,7 +66,11 @@ def __init__(self, self._use_columns_from_df = False self._props['columns'] = self._normalize_columns(columns) self._props['rows'] = rows - self._props['row-key'] = row_key + # if row_key is a list of columns, use the Javascript arrow function syntax, prepending row. to each key + if isinstance(row_key, list): + self._props[':row-key'] = f"row => {'+'.join([f'row.{col}' for col in row_key])}" + else: + self._props['row-key'] = row_key self._props['title'] = title self._props['hide-pagination'] = pagination is None self._props['pagination'] = pagination if isinstance(pagination, dict) else {'rowsPerPage': pagination or 0} @@ -82,7 +86,11 @@ def handle_selection(e: GenericEventArguments) -> None: self.selected.clear() self.selected.extend(e.args['rows']) else: - self.selected = [row for row in self.selected if row[row_key] not in e.args['keys']] + # if row_key is a list of columns, calculate the row_key for each row in the selected list + if isinstance(row_key, list): + self.selected = [row for row in self.selected if ''.join([row[col] for col in row_key]) not in e.args['keys']] + else: + self.selected = [row for row in self.selected if row[row_key] not in e.args['keys']] self.update() arguments = TableSelectionEventArguments(sender=self, client=self.client, selection=self.selected) for handler in self._selection_handlers: From 9127df6e43480109a035f210f8bbf4cbedd2565d Mon Sep 17 00:00:00 2001 From: Alexandr Zarubkin Date: Mon, 16 Dec 2024 12:36:52 +0300 Subject: [PATCH 2/4] Use attribute instead of outer function variable in handle_selection() Because otherwise if row_key is changed later through setter, handle_selection() would still use the outdated value from __init__(). --- nicegui/elements/table.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/nicegui/elements/table.py b/nicegui/elements/table.py index f7800a5cc..ca416ee26 100644 --- a/nicegui/elements/table.py +++ b/nicegui/elements/table.py @@ -68,9 +68,9 @@ def __init__(self, self._props['rows'] = rows # if row_key is a list of columns, use the Javascript arrow function syntax, prepending row. to each key if isinstance(row_key, list): - self._props[':row-key'] = f"row => {'+'.join([f'row.{col}' for col in row_key])}" + self._props[':row-key'] = self._row_key = f"row => {'+'.join([f'row.{col}' for col in row_key])}" else: - self._props['row-key'] = row_key + self._props['row-key'] = self._row_key = row_key self._props['title'] = title self._props['hide-pagination'] = pagination is None self._props['pagination'] = pagination if isinstance(pagination, dict) else {'rowsPerPage': pagination or 0} @@ -87,10 +87,10 @@ def handle_selection(e: GenericEventArguments) -> None: self.selected.extend(e.args['rows']) else: # if row_key is a list of columns, calculate the row_key for each row in the selected list - if isinstance(row_key, list): - self.selected = [row for row in self.selected if ''.join([row[col] for col in row_key]) not in e.args['keys']] + if isinstance(self._row_key, list): + self.selected = [row for row in self.selected if ''.join([row[col] for col in self._row_key]) not in e.args['keys']] else: - self.selected = [row for row in self.selected if row[row_key] not in e.args['keys']] + self.selected = [row for row in self.selected if row[self._row_key] not in e.args['keys']] self.update() arguments = TableSelectionEventArguments(sender=self, client=self.client, selection=self.selected) for handler in self._selection_handlers: @@ -313,7 +313,7 @@ def row_key(self) -> str: @row_key.setter def row_key(self, value: str) -> None: - self._props['row-key'] = value + self._props['row-key'] = self._row_key = value self.update() @property From 053a6c2fe220eb42645cbf4a2d92935d42784a6c Mon Sep 17 00:00:00 2001 From: Alexandr Zarubkin Date: Mon, 16 Dec 2024 13:11:13 +0300 Subject: [PATCH 3/4] Fix row_key getter and setter. --- nicegui/elements/table.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/nicegui/elements/table.py b/nicegui/elements/table.py index ca416ee26..a38fc3499 100644 --- a/nicegui/elements/table.py +++ b/nicegui/elements/table.py @@ -309,11 +309,14 @@ def column_defaults(self, value: Optional[Dict]) -> None: @property def row_key(self) -> str: """Name of the column containing unique data identifying the row.""" - return self._props['row-key'] + return self._row_key @row_key.setter def row_key(self, value: str) -> None: - self._props['row-key'] = self._row_key = value + if isinstance(value, list): + self._props[':row-key'] = self._row_key = f"row => {'+'.join([f'row.{col}' for col in value])}" + else: + self._props['row-key'] = self._row_key = value self.update() @property From e3a9f6598e22108cab10ed695dfe1bf836e60e05 Mon Sep 17 00:00:00 2001 From: Alexandr Zarubkin Date: Mon, 16 Dec 2024 13:18:08 +0300 Subject: [PATCH 4/4] Fix row_key getter and setter. Use row_key property in __init__ for code deduplication. --- nicegui/elements/table.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/nicegui/elements/table.py b/nicegui/elements/table.py index a38fc3499..dfc884db6 100644 --- a/nicegui/elements/table.py +++ b/nicegui/elements/table.py @@ -67,10 +67,7 @@ def __init__(self, self._props['columns'] = self._normalize_columns(columns) self._props['rows'] = rows # if row_key is a list of columns, use the Javascript arrow function syntax, prepending row. to each key - if isinstance(row_key, list): - self._props[':row-key'] = self._row_key = f"row => {'+'.join([f'row.{col}' for col in row_key])}" - else: - self._props['row-key'] = self._row_key = row_key + self.row_key = row_key # should call the property setter self._props['title'] = title self._props['hide-pagination'] = pagination is None self._props['pagination'] = pagination if isinstance(pagination, dict) else {'rowsPerPage': pagination or 0} @@ -314,7 +311,8 @@ def row_key(self) -> str: @row_key.setter def row_key(self, value: str) -> None: if isinstance(value, list): - self._props[':row-key'] = self._row_key = f"row => {'+'.join([f'row.{col}' for col in value])}" + self._row_key = value + self._props[':row-key'] = f"row => {'+'.join([f'row.{col}' for col in value])}" else: self._props['row-key'] = self._row_key = value self.update()