Pārlūkot izejas kodu

refactored todo list to use on_change callbacks

Rodja Trappe 2 gadi atpakaļ
vecāks
revīzija
f6b710b67e
1 mainītis faili ar 39 papildinājumiem un 34 dzēšanām
  1. 39 34
      examples/todo_list/main.py

+ 39 - 34
examples/todo_list/main.py

@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #!/usr/bin/env python3
 from dataclasses import dataclass
 from dataclasses import dataclass
-from typing import List
+from typing import Callable
 
 
 from nicegui import ui
 from nicegui import ui
 
 
@@ -8,58 +8,63 @@ from nicegui import ui
 @dataclass
 @dataclass
 class TodoItem:
 class TodoItem:
     name: str
     name: str
+    on_change: Callable
     done: bool = False
     done: bool = False
 
 
+    def toggle(self) -> None:
+        self.done = not self.done
 
 
-items: List[TodoItem] = [
-    TodoItem('Buy milk', done=True),
-    TodoItem('Clean the house'),
-    TodoItem('Call mom'),
-]
+    def set_name(self, new_name: str) -> None:
+        self.name = new_name
 
 
+    def __setattr__(self, name, value) -> None:
+        super().__setattr__(name, value)
+        if hasattr(self, 'on_change'):
+            self.on_change()
 
 
-def add(name: str) -> None:
-    items.append(TodoItem(name))
-    add_input.value = None
-    render_list.refresh()
 
 
+class ToDoList:
 
 
-def remove(item: TodoItem) -> None:
-    items.remove(item)
-    render_list.refresh()
+    def __init__(self, title: str, on_change: Callable):
+        self.title = title
+        self.items = []
+        self.on_change: Callable = on_change
 
 
+    def add(self, name: str, done: bool = False) -> None:
+        self.items.append(TodoItem(name, self.on_change, done))
+        self.on_change()
 
 
-def toggle(item: TodoItem) -> None:
-    item.done = not item.done
-    render_list.refresh()
-
-
-def rename(item: TodoItem, name: str) -> None:
-    item.name = name
-    render_list.refresh()
+    def remove(self, item: TodoItem) -> None:
+        self.items.remove(item)
+        self.on_change()
 
 
 
 
 @ui.refreshable
 @ui.refreshable
-def render_list():
-    if not items:
-        ui.label('List is empty.')
+def todo_ui():
+    if not todos.items:
+        ui.label('List is empty.').classes('mx-auto')
         return
         return
-    ui.linear_progress(sum(item.done for item in items) / len(items), show_value=False)
+    ui.linear_progress(sum(item.done for item in todos.items) / len(todos.items), show_value=False)
     with ui.row().classes('justify-center w-full'):
     with ui.row().classes('justify-center w-full'):
-        ui.label(f'Completed: {sum(item.done for item in items)}')
-        ui.label(f'Remaining: {sum(not item.done for item in items)}')
-    for item in items:
+        ui.label(f'Completed: {sum(item.done for item in todos.items)}')
+        ui.label(f'Remaining: {sum(not item.done for item in todos.items)}')
+    for item in todos.items:
         with ui.row().classes('items-center'):
         with ui.row().classes('items-center'):
-            ui.checkbox(value=item.done, on_change=lambda _, item=item: toggle(item))
+            ui.checkbox(value=item.done, on_change=lambda _, item=item: item.toggle())
             input = ui.input(value=item.name).classes('flex-grow')
             input = ui.input(value=item.name).classes('flex-grow')
-            input.on('keydown.enter', lambda _, item=item, input=input: rename(item, input.value))
-            ui.button(on_click=lambda _, item=item: remove(item)).props('flat fab-mini icon=delete color=grey')
+            input.on('keydown.enter', lambda _, item=item, input=input: item.set_name(input.value))
+            ui.button(on_click=lambda _, item=item: todos.remove(item)).props('flat fab-mini icon=delete color=grey')
+
 
 
+todos = ToDoList('Shopping', on_change=todo_ui.refresh)
+todos.add('Buy milk', done=True)
+todos.add('Clean the house')
+todos.add('Call mom')
 
 
 with ui.card().classes('w-80 items-stretch'):
 with ui.card().classes('w-80 items-stretch'):
-    ui.label('Todo list').classes('text-semibold text-2xl')
-    render_list()
+    ui.label().bind_text_from(todos, 'title').classes('text-semibold text-2xl')
+    todo_ui()
     add_input = ui.input('New item').classes('mx-12')
     add_input = ui.input('New item').classes('mx-12')
-    add_input.on('keydown.enter', lambda: add(add_input.value))
+    add_input.on('keydown.enter', lambda: (todos.add(add_input.value), add_input.set_value('')))
 
 
 ui.run()
 ui.run()