diff --git a/docs/skills/nicegui/SKILL.md b/docs/skills/nicegui/SKILL.md index e7a80bc..ccfa1e8 100644 --- a/docs/skills/nicegui/SKILL.md +++ b/docs/skills/nicegui/SKILL.md @@ -202,4 +202,5 @@ Return: ## References - Architecture and integration details: [NiceGUI architecture reference](./references/architecture.md) +- Dataclass binding deep dive: [Bindable dataclasses in NiceGUI](./references/binding-dataclasses.md) - Source documentation links: [NiceGUI source documentation](./references/source-documentation.md) diff --git a/docs/skills/nicegui/references/binding-dataclasses.md b/docs/skills/nicegui/references/binding-dataclasses.md new file mode 100644 index 0000000..99bcb36 --- /dev/null +++ b/docs/skills/nicegui/references/binding-dataclasses.md @@ -0,0 +1,119 @@ +# Binding Dataclasses Deep Dive + +This reference explains how to model state with NiceGUI bindable dataclasses and how to avoid common update 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/) + +## What bindable_dataclass changes + +`@binding.bindable_dataclass` extends standard dataclasses by turning fields into bindable properties so UI bindings can propagate immediately when a field is assigned. + +Baseline pattern: + +```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 n: f'User: {n}') +``` + +## Propagation model and performance + +NiceGUI distinguishes between two link types: + +- Bindable properties: efficient, event-like propagation on assignment. +- Active links: polled in a refresh loop (default every 0.1s). + +Practical implications: + +- Prefer bindable dataclasses for frequently updated form state. +- Keep transform functions pure and side-effect free. +- If many active links exist, tune `binding_refresh_interval` in `ui.run(...)` carefully. + +## Dataclass modeling rules that matter for binding + +- Use `field(default_factory=...)` for mutable defaults. +- Avoid `frozen=True` for models that should be edited from UI controls. +- Use `slots=True` only when you have confirmed compatibility with your inheritance and extension needs. +- Keep UI-editable fields explicit and typed. + +Example with safe mutable defaults: + +```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 and binding paths + +NiceGUI supports nested key paths via tuples for nested data (for example dictionaries and nested 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')) +``` + +When using nested dataclasses, keep updates explicit and predictable at the field level. + +## Strictness and refactor safety + +Binding can warn when attributes do not exist. + +- Object attributes are checked by default. +- Dictionary keys are not checked by default. +- Use `strict=True` when you want missing-key warnings for dict-backed state. + +```python +from nicegui import app, ui + +ui.input().bind_value(app.storage.user, 'display_name', strict=True) +``` + +## Common pitfalls and safer alternatives + +- Pitfall: mutating nested mutable values in place and expecting immediate UI sync. +- Safer alternative: assign back to the bound field after updates so change propagation is explicit. + +- Pitfall: heavy transform functions in bindings. +- Safer alternative: keep transformations cheap and deterministic; move heavy work to event handlers. + +- Pitfall: one model shared across unrelated pages or users. +- Safer alternative: scope model instances to page/client/user context as needed. + +## Version notes to remember + +- `bindable_dataclass` added in NiceGUI 2.11.0. +- Binding `strict` behavior documented as added in NiceGUI 3.0.0. +- Tuple paths for nested properties documented as added in NiceGUI 3.10.0. +- Depth-first binding propagation update documented in NiceGUI 2.16.0. + +Verify behavior against the NiceGUI version pinned in your project before relying on version-specific semantics. + +## Quick checklist + +- Choose bindable dataclasses for interactive form-like state. +- Use `default_factory` for mutable fields. +- Keep transform functions pure. +- Use strict mode intentionally. +- Re-check version notes before migration work. diff --git a/docs/skills/nicegui/references/source-documentation.md b/docs/skills/nicegui/references/source-documentation.md index 3137f0e..37b3e39 100644 --- a/docs/skills/nicegui/references/source-documentation.md +++ b/docs/skills/nicegui/references/source-documentation.md @@ -26,8 +26,15 @@ Use these links for framework-specific details. !!! info "NiceGUI sources" - [Pages, routing, and FastAPI integration](https://www.nicegui.io/documentation/section_pages_routing) + - [Binding properties and bindable dataclass](https://www.nicegui.io/documentation/section_binding_properties) - [Security best practices](https://www.nicegui.io/documentation/section_security) +## Python Dataclasses + +!!! info "Python sources" + - [dataclasses module reference](https://docs.python.org/3/library/dataclasses.html) + - [PEP 557: Data Classes](https://peps.python.org/pep-0557/) + ## LangGraph !!! info "LangGraph sources"