diff --git a/website/documentation/content/section_binding_properties.py b/website/documentation/content/section_binding_properties.py index d5e2bd90e..63908fb2f 100644 --- a/website/documentation/content/section_binding_properties.py +++ b/website/documentation/content/section_binding_properties.py @@ -69,3 +69,45 @@ def ui_state(): # .classes('w-full').bind_value(app.storage.user, 'note') # END OF DEMO ui.textarea('This note is kept between visits').classes('w-full').bind_value(app.storage.user, 'note') + + +@doc.demo('Bindable properties for maximum performance', ''' + There are two types of bindings: + + 1. "Bindable properties" automatically detect write access and trigger the value propagation. + Most NiceGUI elements use these bindable properties, like `value` in `ui.input` or `text` in `ui.label`. + Basically all properties with `bind()` methods support this type of binding. + 2. All other bindings are sometimes called "active links". + If you bind a label text to some dictionary entry or an attribute of a custom data model, + NiceGUI's binding module has to actively check if the value changed. + This is done in a `refresh_loop()` which runs every 0.1 seconds. + The interval can be configured via `binding_refresh_interval` in `ui.run()`. + + The "bindable properties" are very efficient and don't cost anything as long as the values don't change. + But the "active links" need to check all bound values 10 times per second. + This can get costly, especially if you bind to complex objects like lists or dictionaries. + + Because it is crucial not to block the main thread for too long, + we show a warning if one step of the `refresh_loop()` takes too long. + You can configure the threshold via `binding.MAX_PROPAGATION_TIME` which defaults to 0.01 seconds. + But often the warning is a valuable indicator for a performance or memory issue. + If your CPU would be busy updating bindings a significant duration, + nothing else could happen on the main thread and the UI "hangs". + + The following demo shows how to define and use bindable properties for a `Demo` class like in the first demo. + The `number` property is now a `BindableProperty`, + which allows NiceGUI to detect write access and trigger the value propagation immediately. +''') +def bindable_properties(): + from nicegui import binding + + class Demo: + number = binding.BindableProperty() + + def __init__(self): + self.number = 1 + + demo = Demo() + ui.slider(min=1, max=3).bind_value(demo, 'number') + ui.toggle({1: 'A', 2: 'B', 3: 'C'}).bind_value(demo, 'number') + ui.number(min=1, max=3).bind_value(demo, 'number')