89 lines
3.5 KiB
Python
89 lines
3.5 KiB
Python
from nicegui import ui
|
|
from src.niceguiasyncelement import AsyncElement, AsyncColumn, AsyncCard
|
|
|
|
|
|
# Example using the generic AsyncElement (returns proper NiceGUI element type)
|
|
class UserCard(AsyncElement[ui.column]):
|
|
async def build(self, user_id: int, *args, **kwargs) -> None:
|
|
user_data = {
|
|
'name': f'User {user_id}',
|
|
'email': f'user{user_id}@example.com',
|
|
'status': 'online' if user_id % 2 == 0 else 'offline'
|
|
}
|
|
|
|
with self:
|
|
with ui.card().classes('w-full max-w-md'):
|
|
ui.label(user_data['name']).classes('text-h6')
|
|
ui.label(user_data['email']).classes('text-caption')
|
|
|
|
with ui.row().classes('w-full justify-between items-center'):
|
|
status_color = 'green' if user_data['status'] == 'online' else 'grey'
|
|
ui.badge(user_data['status']).props(f'color={status_color}')
|
|
ui.button('Edit', icon='edit').props('flat dense')
|
|
|
|
|
|
# Example using direct inheritance approach
|
|
class LoadingCard(AsyncCard):
|
|
async def build(self, title: str, delay: float = 1.0, *args, **kwargs) -> None:
|
|
with self:
|
|
ui.label(title).classes('text-h6 mb-2')
|
|
ui.label('Content loaded successfully!').classes('text-positive')
|
|
with ui.row().classes('gap-2'):
|
|
ui.button('Action 1', icon='star')
|
|
ui.button('Action 2', icon='favorite')
|
|
|
|
|
|
class DataColumn(AsyncColumn):
|
|
async def build(self, data_source: str, *args, **kwargs) -> None:
|
|
columns = [
|
|
{'name': 'name', 'label': 'Name', 'field': 'name', 'required': True, 'align': 'left'},
|
|
{'name': 'age', 'label': 'Age', 'field': 'age', 'sortable': True},
|
|
{'name': 'city', 'label': 'City', 'field': 'city'},
|
|
]
|
|
rows = [
|
|
{'id': 1, 'name': 'Alice', 'age': 25, 'city': 'New York'},
|
|
{'id': 2, 'name': 'Bob', 'age': 30, 'city': 'San Francisco'},
|
|
{'id': 3, 'name': 'Charlie', 'age': 35, 'city': 'London'},
|
|
]
|
|
|
|
with self:
|
|
ui.label(f'Data from {data_source}').classes('text-caption mb-2')
|
|
ui.table(columns=columns, rows=rows, row_key='id').classes('w-full')
|
|
|
|
|
|
@ui.page('/')
|
|
async def main_page():
|
|
ui.label('Typed Async Elements Demo').classes('text-h4 mb-4')
|
|
|
|
# Example 1: Generic AsyncElement - returns ui.column with proper typing
|
|
user_card: ui.column = await UserCard.create(element_type=ui.column, user_id=123)
|
|
user_card.classes('w-full mb-8')
|
|
|
|
# Example 2: Direct inheritance - perfect typing, returns the class instance
|
|
loading_card: LoadingCard = await LoadingCard.create(title="Dashboard Section", delay=0.8)
|
|
loading_card.classes('w-full p-4 mb-8')
|
|
|
|
# Example 3: Column inheritance
|
|
data_column: DataColumn = await DataColumn.create(data_source="users_api")
|
|
data_column.classes('w-full mb-8')
|
|
|
|
# Example 4: Multiple elements with proper typing
|
|
with ui.row().classes('w-full gap-4'):
|
|
for i in range(1, 4):
|
|
card: ui.column = await UserCard.create(element_type=ui.column, user_id=i)
|
|
card.classes('flex-1')
|
|
|
|
# Example 5: Type checker knows all methods are available
|
|
another_card = await LoadingCard.create(title="Another Section")
|
|
another_card.classes('w-full p-4')
|
|
another_card.style('border: 1px solid red') # Type checker knows this method exists
|
|
|
|
|
|
if __name__ in {"__main__", "__mp_main__"}:
|
|
ui.run(
|
|
title='Typed AsyncElements',
|
|
favicon='🔒',
|
|
show=False,
|
|
dark=False,
|
|
port=8080
|
|
) |