-
-
Notifications
You must be signed in to change notification settings - Fork 605
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
Added disable context manager demo #1238
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting idea. Could we do something more interesting than calling await asyncio.sleep(3)
? Something which really takes some time? That would make the usage more clear in my opinion.
And we should use the on_click
parameter not the generic .on('click')
.
Which leads me to my main thought: @falkoschindler should we disable the button by default as long as an async call is processed?
@rodja I'm not sure if we should do it by default. There are certainly use cases where you want to start background tasks that are independent of each other, like "download the current image" or "save the current state to a file". So you might want to start another task while the previous one is still running. Disabling the button would prevent that. |
True. But I assume this kind of scenarios are rare. We could add a parameter to disable the default behavior: ui.button('save state to file', on_click=..., auto_disable=False) |
Let's discuss |
Thanks for the thoughts here. One potential issue with having disable as a default is that it causes the stop cursor to flash for most button clicks, since I assume most buttons would only be disabled for a few milliseconds. For example: from asyncio import sleep
from contextlib import asynccontextmanager
from nicegui import ui
@asynccontextmanager
async def disable_button(button):
button.disable()
try:
yield
finally:
button.enable()
async def on_click(button):
async with disable_button(button):
await sleep(0.01)
b= ui.button("Disable", on_click=lambda: on_click(b))
ui.run() Also to add some examples of where I am using this:
Unfortunately none of those examples lend themselves easily to demo code. I'll see if I can think of something better other than sleep to stick into this demo. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just added some remarks about the code.
Regarding a more realistic example: Maybe we can use something like https://httpbin.org/delay/1
which returns an HTTP response after a certain delay (1 second in this case).
You mentioned a flash when disabling the button for a very short time. This only happens if the delay is awaited asynchronously. For short synchronous event handlers, the disable()
call won't be sent to the client before enable()
is called. But I'm still not sure how to integrate this feature into the existing API. I tend towards an opt-in like ui.button(..., disable_while_click_handling: bool = False)
.
@BrianLandry Are you still working on this PR? Or should we take over? It's up to you, just let us know. 🙂 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry for the slow response, this got lost on my todo list.
Thank you for all the feedback! I'm new to async and learned a lot from your comments. I think I addressed everything, but I'm heading off on a vacation, so please feel free to take over the PR from here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @BrianLandry! Looks all good to me. Let's merge! 🥳
This adds a demo for a context manager I have been using frequently. It will disable the button for the duration of an async process. It is a useful tool to make sure the user does trigger the click a second time while something is running in the background. I thought it may be useful to add on as an example.