-
-
Notifications
You must be signed in to change notification settings - Fork 775
Introduce API to build Single Page Applications (SPAs) #2811
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Integrated single page app into Client.open so navigation to SPA pages is redirected. Fixed bug with forward and backwards navigation between SPA pages. Collecting data from original pages to able to apply the original page title.
Integrated single page app into Client.open so navigation to SPA pages is redirected. Fixed bug with forward and backwards navigation between SPA pages. Collecting data from original pages to able to apply the original page title.
Fixed a bug which could occur when open was called before the UI was set up
…s registry in Client. General clean-up Added titles to sample app Added docu to SPA
4b89fb3
to
13f29ac
Compare
…the structure of the root page, the possibility to override the class and implement custom routing and to react to the creation of sessions. * Added samples for the single page router * Refactored the Login sample with the new possibilities and making use of Pydantic as an example for a cleaner code base
Thank you @Alyxion. There are a lot of interesting things in here. While you are right that a certain kind of applications my want to combine SPA and "per tab storage", it would make review and discussions simpler if you could create two separate pull requests for these features. |
…in the current Client instance - which in practice means "per browser tab".
Moved context import to top of the file
Thank you for the optimizations, its taking shape. As you saw I massively simplified Frame to move nearly all logic to a single location in the SinglePageRouter. Other than that there were still some routing issues between different outlets, within outlets hierarchies etc. I fixed and wrote tests to ensure it stays that way. Other than that there are still two missing feautures on my todo list:
One thing is also that I quite regularly see the wait for the client.connected to timeout. It does not have any negative impact and I also know for sure that the client connected successfully within this time as I need to receive its data etc. - this make it especially odd. If you have any idea what might lead to this this were appreciated. I also btw once more reviewed your question above regarding So e.g you have Some intense weeks ahead, so beyond major bugfixes I will likely continue on this end of March, doing the last refinemenets and a summary of the classes and changes involved as discussed above. |
I started a checklist of open topics and todos in the description of this PR. That way we can better track what we still need to do. |
this makes the API much simpler: there is just "content" which can be nested via yield statement
I created Alyxion#4 which merges |
Thanks for the changes. As written above already I'm quite skeptical about unifying the name completely - though I like the possibility allowing not to yield, e.g. in the just mentioned example that the outlet already decides / detects, that further nesting shall anyway be blocked b/c of a not available database or similar situations. We have a quite large app meanwhile, 3 outlets, dozens of views where the |
The roles are not so different. Both hold UI elements, both contain "layout". The only difference is that the leafs do not contain sub-content which can be changed via routes. If your app is big and you need that differentiation, you can always introduce your own function naming scheme -- or structure with submodules. I think the API should be as simple as possible and not enforce to many concepts. Especially for new users.
In my understanding, this is a different topic and has nothing to do with Outlet/View vs Content. In the checklist I named it "rethink architecture of 'builder routing' as opposite to 'real routing' via backend". I would like to try using an approach like FastAPI/Starlette Middlewares instead of on_navigate parameter -- but that is still a few weeks in the future I guess. |
One major remark here which came up in our projects: For most web pages its is common to have the mai landin page at the domains or subdomain's root, so as a classic nicegui page via When "reserving" the root via One way to solve it were not using placeholders at all when registering the main outlet but adding one router per Outlet.view aka nested sublets. Ideas? |
We at Zaubereug are still totally committed to get SPAs into NiceGUI. As discussed a few weeks ago in a video call with @Alyxion we are therefore taking lead in getting this huge PR into a mergable state. First order of business is the integration of Alyxion#4 which combines |
I removed the following part from the description because it does not describe the goal of this PR: NiceGUI is still lacking three for us very crucial features Streamlit offers:
This (still work in progress) pull request tries to resolve at least most of the points above. It shall not yet resolve the situation that a user has an unstable internet connection and thus looses the connection to a server completely and needs to reconnect. Persistent connectionIn a scenario where you want to serve your NiceGUI solution not to hundreds of users there is after a certain point no way around scaling the solution over multiple processes, CPUs or over multiple servers. If you need to load/keep alive large amounts of data per user w/o involving an external database this requires that the whole user session, even between page changes, is bound to one single process on one specific server. Streamlits uses a SPA approach here thus it creates a WebSockets connection once and all follow-up page and tab changes are just virtual thus changing the URL and browser history in the browser using pushstate but never really loading a new page using GET. As discussed in the Add app.storage.tab or similar (1308) and in Discord there are several use cases where this is crucial to retain in-memory data on a "per session" basis, see below, which consequently requires that there is such a session in the first place. Per tab storageA data storage possibility per tab is cruicial to enable the user to create multiple app instances with different login credentials, configurations and views on a per tab basis. This is on purpose volatile so that user-credentials, critical business data etc. are gone once the browser tab was closed and the connection timed out. This shall match the current behavior of st.session_state. In-memory storage of complex objectsThe possibility to store living, non-JSON compatible objects such as Pandas tables, ML model weights etc. on a "per tab" basis and make them as easy accessible among different pages, global helper classes etc. as currently app.storage.user. Update: Extracted the app.storage.session feature into a separate pull request 2820 |
NiceGUI is for us at Lechler a really awesome solution and step forward from Streamlit in regards of the visualization of live and streaming data as it puts the dev far more in control of which sub elements and page regions are updated when. This PR started with many ideas and concepts to add crucial features needed by Lechler. It now focuses on providing a first mergeable implementation to develop Single Page Applications (SPAs).
Open ToDos/Topics we need to adress
Outlet
without yield (and then get rid ofOutletView
and renameOutlet
toContent
or similar); see Simplify API by merging Outlet and View Alyxion/nicegui#4 for WIPContent
and similar stuff inSinglePageTarget
; and do we have to do separate routing in frame.js?on_navigate
in favour of a class registration in the style of Starlet middlewares?SinglePageTarget.valid
member variableuser_data
(it's more analog to parameters in function calls)buildier_utils
andSinglePageTarget
have similar if/else instance checks; we should consolidate