Skip to content

Commit

Permalink
Set selection, expansion and tick props for ui.tree only when needed (
Browse files Browse the repository at this point in the history
#3902)

This PR solves a problem mentioned in #3840: The `ui.tree` element
should only be in "selection mode" if there's a selection handler.
Otherwise clicking on a node label should expand/collapse it rather than
toggling the selection.

Click on label expands/collapses node:
```py
ui.tree([
    {'id': 'numbers', 'children': [{'id': '1'}, {'id': '2'}]},
    {'id': 'letters', 'children': [{'id': 'A'}, {'id': 'B'}]},
], label_key='id')
```

Click on label selects/deselects node:
```py
ui.tree([
    {'id': 'numbers', 'children': [{'id': '1'}, {'id': '2'}]},
    {'id': 'letters', 'children': [{'id': 'A'}, {'id': 'B'}]},
], label_key='id', on_select=ui.notify)
```

While at it, I also improved expansion and tick props, so that they are
only defined if event handlers or a tick strategy is given.
  • Loading branch information
falkoschindler authored Oct 20, 2024
1 parent 526c66b commit 0a32160
Showing 1 changed file with 16 additions and 5 deletions.
21 changes: 16 additions & 5 deletions nicegui/elements/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ def __init__(self,
self._props['node-key'] = node_key
self._props['label-key'] = label_key
self._props['children-key'] = children_key
self._props['selected'] = None
self._props['expanded'] = []
self._props['ticked'] = []
if tick_strategy is not None:
self._props['tick-strategy'] = tick_strategy
if on_select:
self._props['selected'] = None
if on_expand:
self._props['expanded'] = []
if on_tick or tick_strategy:
self._props['ticked'] = []
self._props['tick-strategy'] = tick_strategy or 'leaf'
self._select_handlers = [on_select] if on_select else []
self._expand_handlers = [on_expand] if on_expand else []
self._tick_handlers = [on_tick] if on_tick else []
Expand Down Expand Up @@ -79,6 +81,7 @@ def handle_ticked(e: GenericEventArguments) -> None:

def on_select(self, callback: Handler[ValueChangeEventArguments]) -> Self:
"""Add a callback to be invoked when the selection changes."""
self._props.setdefault('selected', None)
self._select_handlers.append(callback)
return self

Expand All @@ -87,6 +90,7 @@ def select(self, node_key: Optional[str]) -> Self:
:param node_key: node key to select
"""
self._props.setdefault('selected', None)
if self._props['selected'] != node_key:
self._props['selected'] = node_key
self.update()
Expand All @@ -98,11 +102,14 @@ def deselect(self) -> Self:

def on_expand(self, callback: Handler[ValueChangeEventArguments]) -> Self:
"""Add a callback to be invoked when the expansion changes."""
self._props.setdefault('expanded', [])
self._expand_handlers.append(callback)
return self

def on_tick(self, callback: Handler[ValueChangeEventArguments]) -> Self:
"""Add a callback to be invoked when a node is ticked or unticked."""
self._props.setdefault('ticked', [])
self._props.setdefault('tick-strategy', 'leaf')
self._tick_handlers.append(callback)
return self

Expand All @@ -111,6 +118,7 @@ def tick(self, node_keys: Optional[List[str]] = None) -> Self:
:param node_keys: list of node keys to tick or ``None`` to tick all nodes (default: ``None``)
"""
self._props.setdefault('ticked', [])
self._props['ticked'][:] = self._find_node_keys(node_keys).union(self._props['ticked'])
self.update()
return self
Expand All @@ -120,6 +128,7 @@ def untick(self, node_keys: Optional[List[str]] = None) -> Self:
:param node_keys: list of node keys to untick or ``None`` to untick all nodes (default: ``None``)
"""
self._props.setdefault('ticked', [])
self._props['ticked'][:] = set(self._props['ticked']).difference(self._find_node_keys(node_keys))
self.update()
return self
Expand All @@ -129,6 +138,7 @@ def expand(self, node_keys: Optional[List[str]] = None) -> Self:
:param node_keys: list of node keys to expand (default: all nodes)
"""
self._props.setdefault('expanded', [])
self._props['expanded'][:] = self._find_node_keys(node_keys).union(self._props['expanded'])
self.update()
return self
Expand All @@ -138,6 +148,7 @@ def collapse(self, node_keys: Optional[List[str]] = None) -> Self:
:param node_keys: list of node keys to collapse (default: all nodes)
"""
self._props.setdefault('expanded', [])
self._props['expanded'][:] = set(self._props['expanded']).difference(self._find_node_keys(node_keys))
self.update()
return self
Expand Down

0 comments on commit 0a32160

Please sign in to comment.