Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Discussion options

Hi, I recently discovered NiceGUI and I am very much interested in giving it a go, but there are some things I don't quite understand after working through the documentation.

The NiceGUI documentation on bindings says "NiceGUI is able to directly bind UI elements to models" and provides this code example:

from nicegui import ui

class Demo:
    def __init__(self):
        self.number = 1

demo = Demo()
v = ui.checkbox('visible', value=True)
with ui.column().bind_visibility_from(v, 'value'):
    ui.slider(min=1, max=3).bind_value(demo, 'number')
    ui.toggle({1: 'A', 2: 'B', 3: 'C'}).bind_value(demo, 'number')
    ui.number().bind_value(demo, 'number')

ui.run()

I understand the example is using script mode and the "code will be executed once per client connection". Just from looking at the code though, demo seems to be a module-level variable that I expect to be initialized exactly once when I run the above file to start the server.

So, my first question would be: Will an individual demo object be created for each client that connects to the app, or will there be only one single demo object, so that the state of the slider, toggle and number will be shared across multiple clients?

Reading about pages, they seem to be the preferred way to structure an application. Intuitively, I would upgrade the above code like this:

from nicegui import ui

class Demo:
    def __init__(self):
        self.number = 1

@ui.page("/my_page")
def my_page():
    demo = Demo()
    v = ui.checkbox('visible', value=True)
    with ui.column().bind_visibility_from(v, 'value'):
        ui.slider(min=1, max=3).bind_value(demo, 'number')
        ui.toggle({1: 'A', 2: 'B', 3: 'C'}).bind_value(demo, 'number')
        ui.number().bind_value(demo, 'number')

ui.run()

Would that be correct? Would it yield the same behavior? Now it definitely looks like there should be one demo object per client (or per tab?) that visits /my_page and triggers the page builder function. But what happens when demo goes out of scope after the page is built?

As an immediate follow-up, in case there is some magic happening here, where is the state represented by demo actually stored? On the server or on the client? In a plain object, or in some data structure that allows association with specific clients?

Finally, NiceGUI also has storage with well-documented behavior that can also be bound to UI element properties. How does the demo model compare to the storage options and where does it fit into the storage feature comparison table? What type of object would you bind UI element properties to when assembling your own UI components out of the ui elements?

You must be logged in to vote

Hi @NiklasKappel,

In the context of multiple visitors, this demo might be a bit misleading. As you noticed correctly, it is using script mode because there is no page function, so NiceGUI creates one for you. This function wraps all code, including the Demo class definition and the demo instance, which kind of misses the point of such a data model class. The app is still working, but - yes - every visitor gets to see a new demo instance.

Your second snippet results in the same behavior, because there's a new demo instance for every visitor. The only technical difference is that all instances are created from the same Demo class, not like in the first snippet where even the class was creat…

Replies: 1 comment

Comment options

Hi @NiklasKappel,

In the context of multiple visitors, this demo might be a bit misleading. As you noticed correctly, it is using script mode because there is no page function, so NiceGUI creates one for you. This function wraps all code, including the Demo class definition and the demo instance, which kind of misses the point of such a data model class. The app is still working, but - yes - every visitor gets to see a new demo instance.

Your second snippet results in the same behavior, because there's a new demo instance for every visitor. The only technical difference is that all instances are created from the same Demo class, not like in the first snippet where even the class was created per visitor.

If you move the demo out of the page function, it will be shared by all visitors. Moving the slider on one browser tab should update the UI on all other tabs as well.

The state is stored on the server, in a simple Python object. Clients are updated via websocket connections that are kept alive until they disconnect.

The storage module allows to store data, e.g., across server restarts. Where does your demo end up in the table?

  • Across tabs/browsers/page reloads: depending on whether demo is created in global scope or in a page function
  • Across server restarts: no
  • Needs client connection: no
  • Write only before response: no
  • Needs serializable data: no
  • Needs storage_secret: no

What type of object to use? That strongly depends on your requirements (see the storage table).

You must be logged in to vote
0 replies
Answer selected by NiklasKappel
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
🙏
Q&A
Labels
None yet
2 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.