dialog with property

This commit is contained in:
2025-09-23 05:26:18 +02:00
parent 1012cf3d73
commit 02d7513b77
4 changed files with 116 additions and 51 deletions

View File

@@ -10,6 +10,9 @@ class ConfirmDialog(AsyncColumn):
async def build(self, message: str, title: str = "Confirm"): async def build(self, message: str, title: str = "Confirm"):
"""Build the dialog content""" """Build the dialog content"""
# Set dialog size using the property
self.dialog_size = 'w-96'
ui.label(title).classes('text-h6') ui.label(title).classes('text-h6')
ui.label(message) ui.label(message)
ui.space() ui.space()
@@ -24,6 +27,10 @@ class FormDialog(AsyncColumn):
async def build(self, title: str = "Enter Information"): async def build(self, title: str = "Enter Information"):
"""Build the form dialog""" """Build the form dialog"""
# Set a wider dialog size for the form
if hasattr(self, '_dialog'):
self.dialog_size = 'w-1/2'
ui.label(title).classes('text-h6') ui.label(title).classes('text-h6')
# Create input fields # Create input fields
@@ -93,6 +100,9 @@ async def main():
async def show_inline_dialog(): async def show_inline_dialog():
class QuickDialog(AsyncColumn): class QuickDialog(AsyncColumn):
async def build(self): async def build(self):
# Smaller dialog size for simple questions
self.dialog_size = 'w-72'
ui.label('Quick Question').classes('text-h6') ui.label('Quick Question').classes('text-h6')
ui.label('Do you like this feature?') ui.label('Do you like this feature?')
@@ -106,6 +116,30 @@ async def main():
ui.button('Show Quick Dialog', on_click=show_inline_dialog) ui.button('Show Quick Dialog', on_click=show_inline_dialog)
# Example with dynamic sizing based on content
async def show_dynamic_dialog():
class DynamicDialog(AsyncColumn):
async def build(self, items_count: int = 3):
# Adjust size based on content
if items_count <= 3:
self.dialog_size = 'w-96'
else:
self.dialog_size = 'w-1/2'
ui.label(f'Dynamic Dialog with {items_count} items').classes('text-h6')
for i in range(items_count):
ui.label(f'Item {i + 1}: This is some content for item {i + 1}')
ui.space()
ui.button('Close', on_click=lambda: self._dialog.submit(f'Closed with {items_count} items'))
for count in [2, 5]:
result = await DynamicDialog.as_dialog(items_count=count)
ui.notify(f'Result: {result}')
ui.button('Show Dynamic Dialogs', on_click=show_dynamic_dialog)
if __name__ in {"__main__", "__mp_main__"}: if __name__ in {"__main__", "__mp_main__"}:
ui.run(title='Async Dialog Example', port=8085) ui.run(title='Async Dialog Example', port=8085)

View File

@@ -1,10 +1,9 @@
from .base import AsyncElement from .base import AsyncElement
from .elements import (AsyncColumn, AsyncRow, AsyncCard, AsyncScrollArea) from .elements import (AsyncColumn, AsyncRow, AsyncCard)
__all__ = [ __all__ = [
'AsyncElement', 'AsyncElement',
'AsyncColumn', 'AsyncColumn',
'AsyncRow', 'AsyncRow',
'AsyncCard', 'AsyncCard',
'AsyncScrollArea'
] ]

View File

@@ -1,19 +1,35 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Self, Any from typing import Self, Any, Optional
from nicegui import ui from nicegui import ui
class AsyncColumn(ui.column, ABC): class AsyncColumn(ui.column, ABC):
"""Async column that inherits from ui.column for perfect typing""" """Async column that inherits from ui.column for perfect typing"""
_dialog: Optional[ui.dialog] = None
_dialog_card: Optional[ui.card] = None
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self._dialog_size: str | None = None
@abstractmethod @abstractmethod
async def build(self, *args, **kwargs) -> None: async def build(self, *args, **kwargs) -> None:
"""Build/setup the element - must be implemented by subclasses""" """Build/setup the element - must be implemented by subclasses"""
... ...
@property
def dialog_size(self) -> str | None:
"""Get or set the dialog size (e.g., 'w-1/2', 'w-96', 'max-w-4xl')"""
return self._dialog_size
@dialog_size.setter
def dialog_size(self, value: str | None) -> None:
"""Set the dialog size - applies to the dialog if it exists"""
self._dialog_size = value
if self._dialog_card:
self._dialog_card.classes(value)
@classmethod @classmethod
async def create(cls, *args, **kwargs) -> Self: async def create(cls, *args, **kwargs) -> Self:
"""Factory method to create and build a column instance""" """Factory method to create and build a column instance"""
@@ -38,14 +54,20 @@ class AsyncColumn(ui.column, ABC):
dialog.open() dialog.open()
# Build the element inside the dialog with a card # Build the element inside the dialog with a card
with dialog, ui.card(): with dialog:
with ui.card().style('max-width: none;') as dialog_card:
instance = cls() instance = cls()
# Store dialog reference for potential use in build() # Store dialog reference for potential use in build()
instance._dialog = dialog # pyright: ignore[reportAttributeAccessIssue] instance._dialog = dialog # pyright: ignore[reportAttributeAccessIssue]
instance._dialog_card = dialog_card
await instance.build(*args, **kwargs) await instance.build(*args, **kwargs)
# Apply dialog size if set
if hasattr(instance, '_dialog_size') and instance._dialog_size:
dialog.classes(add=instance._dialog_size)
# Await the dialog result # Await the dialog result
result = await dialog result = await dialog
@@ -58,14 +80,30 @@ class AsyncColumn(ui.column, ABC):
class AsyncRow(ui.row, ABC): class AsyncRow(ui.row, ABC):
"""Async row that inherits from ui.row for perfect typing""" """Async row that inherits from ui.row for perfect typing"""
_dialog: Optional[ui.dialog] = None
_dialog_card: Optional[ui.card] = None
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self._dialog_size: str | None = None
@abstractmethod @abstractmethod
async def build(self, *args, **kwargs) -> None: async def build(self, *args, **kwargs) -> None:
"""Build/setup the element - must be implemented by subclasses""" """Build/setup the element - must be implemented by subclasses"""
... ...
@property
def dialog_size(self) -> str | None:
"""Get or set the dialog size (e.g., 'w-1/2', 'w-96', 'max-w-4xl')"""
return self._dialog_size
@dialog_size.setter
def dialog_size(self, value: str | None) -> None:
"""Set the dialog size - applies to the dialog if it exists"""
self._dialog_size = value
if self._dialog_card:
self._dialog_card.classes(value)
@classmethod @classmethod
async def create(cls, *args, **kwargs) -> Self: async def create(cls, *args, **kwargs) -> Self:
"""Factory method to create and build a column instance""" """Factory method to create and build a column instance"""
@@ -79,11 +117,17 @@ class AsyncRow(ui.row, ABC):
dialog = ui.dialog() dialog = ui.dialog()
dialog.open() dialog.open()
with dialog, ui.card(): with dialog:
with ui.card().style('max-width: none;') as dialog_card:
instance = cls() instance = cls()
instance._dialog = dialog # pyright: ignore[reportAttributeAccessIssue] instance._dialog = dialog # pyright: ignore[reportAttributeAccessIssue]
instance._dialog_card = dialog_card
await instance.build(*args, **kwargs) await instance.build(*args, **kwargs)
# Apply dialog size if set
if hasattr(instance, '_dialog_size') and instance._dialog_size:
dialog.classes(instance._dialog_size)
result = await dialog result = await dialog
dialog.clear() dialog.clear()
return result return result
@@ -92,14 +136,30 @@ class AsyncRow(ui.row, ABC):
class AsyncCard(ui.card, ABC): class AsyncCard(ui.card, ABC):
"""Async card that inherits from ui.card for perfect typing""" """Async card that inherits from ui.card for perfect typing"""
_dialog: Optional[ui.dialog] = None
_dialog_card: Optional[ui.card] = None
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self._dialog_size: str | None = None
@abstractmethod @abstractmethod
async def build(self, *args, **kwargs) -> None: async def build(self, *args, **kwargs) -> None:
"""Build/setup the element - must be implemented by subclasses""" """Build/setup the element - must be implemented by subclasses"""
... ...
@property
def dialog_size(self) -> str | None:
"""Get or set the dialog size (e.g., 'w-1/2', 'w-96', 'max-w-4xl')"""
return self._dialog_size
@dialog_size.setter
def dialog_size(self, value: str | None) -> None:
"""Set the dialog size - applies to the dialog if it exists"""
self._dialog_size = value
if self._dialog_card:
self._dialog_card.classes(value)
@classmethod @classmethod
async def create(cls, *args, **kwargs) -> Self: async def create(cls, *args, **kwargs) -> Self:
"""Factory method to create and build a card instance""" """Factory method to create and build a card instance"""
@@ -113,45 +173,17 @@ class AsyncCard(ui.card, ABC):
dialog = ui.dialog() dialog = ui.dialog()
dialog.open() dialog.open()
with dialog, ui.card(): with dialog:
instance = cls() with ui.card().style('max-width: none;') as dialog_card:
instance._dialog = dialog # pyright: ignore[reportAttributeAccessIssue]
await instance.build(*args, **kwargs)
result = await dialog
dialog.clear()
return result
class AsyncScrollArea(ui.scroll_area, ABC):
"""Async ScrollArea that inherits from ui.scrol_area for perfect typing"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@abstractmethod
async def build(self, *args, **kwargs) -> None:
"""Build/setup the element - must be implemented by subclasses"""
...
@classmethod
async def create(cls, *args, **kwargs) -> Self:
"""Factory method to create and build a column instance"""
instance = cls()
await instance.build(*args, **kwargs)
return instance
@classmethod
async def as_dialog(cls, *args, **kwargs) -> Any:
"""Create element inside a dialog and await its result"""
dialog = ui.dialog()
dialog.open()
with dialog, ui.card():
instance = cls() instance = cls()
instance._dialog = dialog # pyright: ignore[reportAttributeAccessIssue] instance._dialog = dialog # pyright: ignore[reportAttributeAccessIssue]
instance._dialog_card = dialog_card
await instance.build(*args, **kwargs) await instance.build(*args, **kwargs)
# Apply dialog size if set
if hasattr(instance, '_dialog_size') and instance._dialog_size:
dialog.classes(instance._dialog_size)
result = await dialog result = await dialog
dialog.clear() dialog.clear()
return result return result