100 lines
3.2 KiB
Markdown
100 lines
3.2 KiB
Markdown
# Binding Dataclasses Deep Dive
|
|
|
|
Use this reference to model NiceGUI state with bindable dataclasses and avoid common propagation and performance pitfalls.
|
|
|
|
## Primary Sources
|
|
|
|
- NiceGUI binding docs: [binding properties](https://www.nicegui.io/documentation/section_binding_properties)
|
|
- Python dataclass docs: [dataclasses module](https://docs.python.org/3/library/dataclasses.html)
|
|
- Data class design rationale: [PEP 557](https://peps.python.org/pep-0557/)
|
|
|
|
## Bindable Dataclass Behavior
|
|
|
|
`@binding.bindable_dataclass` extends standard dataclasses by turning fields into bindable properties, allowing UI bindings to propagate when a field is assigned.
|
|
|
|
```python
|
|
from nicegui import binding, ui
|
|
|
|
|
|
@binding.bindable_dataclass
|
|
class Profile:
|
|
name: str = "Ada"
|
|
age: int = 37
|
|
|
|
|
|
profile = Profile()
|
|
|
|
ui.input("Name").bind_value(profile, "name")
|
|
ui.number("Age", min=0).bind_value(profile, "age")
|
|
ui.label().bind_text_from(profile, "name", backward=lambda name: f"User: {name}")
|
|
```
|
|
|
|
## Propagation And Performance
|
|
|
|
NiceGUI distinguishes between two link types:
|
|
|
|
- Bindable properties propagate efficiently when values are assigned.
|
|
- Active links are checked in a refresh loop.
|
|
|
|
Prefer bindable dataclasses for frequently updated form state. Keep binding transforms pure and inexpensive. If an application has many active links, tune `binding_refresh_interval` in `ui.run(...)` only after measuring the impact.
|
|
|
|
## Dataclass Modeling Rules
|
|
|
|
- Use `field(default_factory=...)` for mutable defaults.
|
|
- Avoid `frozen=True` for models edited by UI controls.
|
|
- Use `slots=True` only after confirming compatibility with inheritance and extension needs.
|
|
- Keep UI-editable fields explicit and typed.
|
|
|
|
```python
|
|
from dataclasses import field
|
|
|
|
from nicegui import binding
|
|
|
|
|
|
@binding.bindable_dataclass
|
|
class Filters:
|
|
query: str = ""
|
|
tags: list[str] = field(default_factory=list)
|
|
```
|
|
|
|
## Nested Structures
|
|
|
|
NiceGUI supports tuple paths for nested data structures.
|
|
|
|
```python
|
|
from nicegui import ui
|
|
|
|
data = {"user": {"name": "Ada"}}
|
|
|
|
ui.input("Name").bind_value(data, ("user", "name"))
|
|
ui.label().bind_text_from(data, ("user", "name"))
|
|
```
|
|
|
|
Keep nested dataclass updates explicit and predictable at the field level.
|
|
|
|
## Strictness And Refactor Safety
|
|
|
|
- Object attributes are checked by default.
|
|
- Dictionary keys are not checked by default.
|
|
- Use `strict=True` when missing dictionary keys should produce warnings.
|
|
|
|
```python
|
|
from nicegui import app, ui
|
|
|
|
ui.input().bind_value(app.storage.user, "display_name", strict=True)
|
|
```
|
|
|
|
## Common Pitfalls
|
|
|
|
- In-place mutation may not produce immediate UI synchronization. Assign the updated value back to the bound field.
|
|
- Heavy binding transforms can degrade refresh performance. Move expensive work to event handlers or services.
|
|
- State shared across unrelated pages or users can leak data. Scope models to the appropriate page, client, or user context.
|
|
|
|
## Version Checks
|
|
|
|
- `bindable_dataclass` was added in NiceGUI 2.11.0.
|
|
- Depth-first binding propagation was documented in NiceGUI 2.16.0.
|
|
- Binding `strict` behavior was documented in NiceGUI 3.0.0.
|
|
- Tuple paths for nested properties were documented in NiceGUI 3.10.0.
|
|
|
|
Verify these behaviors against the NiceGUI version pinned by the target project. |