Nicegui Tree with toggle buttons #3085
-
QuestionIm trying to create a tree in nicegui where every element has a toggle button. This is what i got so far: from nicegui import events, ui
def toggleUpdate(e: events.GenericEventArguments) -> None:
print(tree._props['nodes'])
tree = ui.tree([
{'id': 'numbers', 'description': 'Just some numbers', 'update': True, 'children': [
{'id': '1', 'description': 'The first number', 'update': False},
{'id': '2', 'description': 'The second number', 'update': True},
]},
{'id': 'letters', 'description': 'Some latin letters', 'update': True, 'children': [
{'id': 'A', 'description': 'The first letter', 'update': True},
{'id': 'B', 'description': 'The second letter', 'update': True},
]},
], label_key='id', on_select=lambda e: ui.notify(e.value))
tree.add_slot('default-header', '''
<span :props="props">Node <strong>{{ props.node.id }}</strong></span>
''')
tree.add_slot('default-body', r'''
<span :props="props">Description: "{{ props.node.description }}" <q-toggle
v-model="props.node.update"
label="Elemente updaten"
left-label
@update:model-value="() => $parent.$emit('toggleUpdate', props.node)"
/></span>
''')
ui.button("Test", on_click=lambda: toggleUpdate("TEST"))
tree.on('toggleUpdate', toggleUpdate)
tree.on('update:model-value', lambda e: ui.notify(e.args))
ui.run() The tree works fine, but the data is not changed when I toggle the button and also the toggleUpdate event is not triggered. What am I doing wrong? It seems to work with tables: https://github.com/zauberzeug/nicegui/blob/dfa98b190faeea66d769123e5b1851868b166e8a/examples/editable_table/main.py |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
Hi @Ottokranz, This one is a bit tricky. For some reason the toggle component seems to be nested more deeply, so that we need to write And to reflect the toggle value in the data model, we need to handle the event arguments and update the nodes accordingly. Unfortunately there's no API for iterating nodes or searching them by ID, so we need to implement it ourselves: nodes = [
{'id': 'numbers', 'description': 'Just some numbers', 'update': True, 'children': [
{'id': '1', 'description': 'The first number', 'update': False},
{'id': '2', 'description': 'The second number', 'update': True},
]},
{'id': 'letters', 'description': 'Some latin letters', 'update': True, 'children': [
{'id': 'A', 'description': 'The first letter', 'update': True},
{'id': 'B', 'description': 'The second letter', 'update': True},
]},
]
def iterate_nodes(nodes: List[Dict]) -> Iterator[Dict]:
for node in nodes:
yield node
yield from iterate_nodes(node.get('children', []))
def toggle_update(e: events.GenericEventArguments) -> None:
for node in iterate_nodes(nodes):
if node['id'] == e.args['id']:
node.update(e.args)
break
tree = ui.tree(nodes, label_key='id', on_select=lambda e: ui.notify(e.value))
tree.add_slot('default-header', r'''
<span :props="props">Node <strong>{{ props.node.id }}</strong></span>
''')
tree.add_slot('default-body', r'''
<q-toggle
:props="props"
v-model="props.node.update"
label="Elemente updaten"
left-label
@update:model-value="() => $parent.$parent.$parent.$emit('toggleUpdate', props.node)"
/>
''')
tree.on('toggleUpdate', toggle_update) |
Beta Was this translation helpful? Give feedback.
Hi @Ottokranz,
This one is a bit tricky. For some reason the toggle component seems to be nested more deeply, so that we need to write
$parent.$parent.$parent.$emit()
to emit from the tree element. I wonder if there's a more elegant way to do that.And to reflect the toggle value in the data model, we need to handle the event arguments and update the nodes accordingly. Unfortunately there's no API for iterating nodes or searching them by ID, so we need to implement it ourselves: