I recently got acquainted with the NiceGUI library for python and decided to rewrite the Todo List demo in one kind of class.
One list works well, when adding a second one there are difficulties: one of the lists may not respond to the fact that I mark the task as completed, until I delete or add a task there, then the second list stops responding.
Here is the source code: https://github.com/zauberzeug/nicegui/blob/main/examples/todo_list/main.py And here is my code:
from nicegui import ui
from dataclasses import dataclass
from typing import List
@dataclass
class TodoItem:
name: str
done: bool = False
class TodoListComponent:
def __init__(self, title: str, items: List[TodoItem] = None):
self.title = title
if items:
self.items = items
else:
self.items = []
def view(self):
with ui.card().classes('w-80 items-stretch'):
ui.label(self.title).classes('text-semibold test-2xl')
self.on_change()
add_input = ui.input('New item').classes('mx-12')
add_input.on('keydown.enter', lambda: (self.add(add_input.value),
add_input.set_value('')))
def add(self, name, done=False):
self.items.append(TodoItem(name=name))
self.on_change.refresh()
def remove(self, item):
self.items.remove(item)
self.on_change.refresh()
@ui.refreshable
def on_change(self):
print(self.title, self.items) # when I mark a task from the first list as completed, there may be information from the second
if not self.items:
ui.label('List is empty.').classes('mx-auto')
return
done_items = sum(item.done for item in self.items)
ui.linear_progress(done_items / len(self.items), show_value=False)
with ui.row().classes('justify-center w-full'):
ui.label(f'Completed {done_items}')
ui.label(f'Remaining: {len(self.items) - done_items}')
for item in self.items:
with ui.row().classes('items-center'):
ui.checkbox(value=item.done, on_change=self.on_change.refresh).bind_value(item, 'done')
ui.input(value=item.name).classes('flex-grow').bind_value(item, 'name')
ui.button(on_click=lambda item=item: self.remove(item), icon='delete')\
.props('flat fab-mini color=grey')
todos = TodoListComponent('My Friday')
todos.add('Order pizza', done=True)
todos.add('New NiceGUI Release')
todos.add('Clean the house')
todos.add('Call mom')
todos.view()
todos_2 = TodoListComponent('My Monday')
todos_2.add('Order pizza', done=True)
todos_2.add('New NiceGUI Release')
todos_2.add('Clean the house')
todos_2.add('Call mom')
todos_2.view()
ui.run()
I'm just wondering if it's possible to create widgets on NiceGUI in the same way as it is done on javascript frameworks (or some alternatives in python)
I'm not sure why, but replacing
on_change=self.on_change.refresh
with
on_change=lambda: self.on_change.refresh()
seems to resolve the issue with refreshing the wrong list. I'll probably file a bug report, since this is rather unexpected.
Edit: Here it is.