This follows on my from my question about applying a lock. I want to extend this by having a checkbox to lock each single number input, and another checkbox to lock all inputs.
The problem I have is that my function lock_all seems to get run always, when I only want it to run when it is clicked. Any changes to Lock 1 or Lock 2 get over-ridden - I can either have everything locked, or nothing locked! Any ideas how I could get this working?
Here is some working code to explain:
import streamlit as st
# need to declare the lock before function
if "lock_all" not in st.session_state:
st.session_state["lock_all"] = False
# this is run by the lock all button
def lock_all():
st.session_state["lock_1"] = st.session_state["lock_all"]
st.session_state["lock_2"] = st.session_state["lock_all"]
# lock all checkbox
lock_all_box = st.checkbox(
"Lock all",
value=False,
on_change=lock_all(),
key="lock_all")
# lock_1 checkbox
lock_1 = st.checkbox(
"Lock 1",
value=False,
key="lock_1")
# lock_2 checkbox
lock_2 = st.checkbox(
"Lock 2",
value=False,
key="lock_2")
# lockable parameter 1
param_1 = st.number_input(
"Parameter 1",
key="param1",
disabled=st.session_state.lock_1,)
# lockable parameter 2
param_2 = st.number_input(
"Parameter 2",
key="param2",
disabled=st.session_state.lock_2,)
You are executing the function here rather than passing it to the checkbox. The on_change argument expects a function object, i.e., lock_all. In your case, lock_all() just executes that function and returns None, which is then passed to the on_change argument.
Excellent thanks!.. sorry this is more of a python question than a streamlit question, but if lock_all takes args (in my case, I have a grid of parameters, with each row being several lockable parameters, with a lock_all per row), how do I get the arg (the row number) into the function object?
@altanner Thatâs a great question! Actually, st.checkbox (and most other streamlit widgets) have an args function that let you pass a tuple of arguments that get passed to the callback. See the docs for more st.checkbox - Streamlit Docs
Amazing, thank you both @blackary and @edsaac, all working now! So pleased! (when this thing is closer to ready Iâll drop it in the community threads, and itâll blow your minds! ha, well, maybe).
This is close enough to my problem that Iâm re-opening this rather than a full, new ticket. How do I prevent one widget from triggering the on_change even of another? Using the above example:
Where I want the user to be able to interact with the checkbox, Item1, without triggering Item2, even if there is text in Item2.
So,
Type some text in to the input box, but instead of pressing Enter, just click on the checkbox. As it is, my_func() is triggered for Item2 when Item1 is clicked.
Except it isnât preciselyâŠwhich is what Iâm struggling with. Itâs a combination of âvalue has changedâ and âany actionâ is taken. Basically, I would expect (want) this to behave as an atomic action that only takes place when the widget Iâm interacting with takes an actionâŠnot when any, other widget is activated.
Is there some other method that is expected to fill that use case and Iâm just expecting a convenience/convention that doesnât exist in Streamlit?
The value doesnât change when you type but when you either press Enter or take the focus away from the widget. The callback is triggered not because you interact with the checkbox but because the text input losses the focus. AFAIK there is no way (within the streamlit framework) to discriminate beetween pressing Enter and losing the focus.
It looks like what you actually want is to detect a keystroke. That is low-level functionality that Streamlit doesnât offer. Why do you need that?
âNeedâ is probably strong here. Iâm just learning the whole thing, Python, UI implementation, etc. And, Streamlit was used as the web UI example in a video course. So, a) thank you for the clarification about âtaking focus awayââŠthat at least helps sort out the logic in my headâŠheh. And, b) the situation Iâm working with right now that led to this line of questioning is: A basic task list editor that takes the text_input and turns that into a checklist item above. Once a checkbox item is added to the list of boxes, the user can click any checkbox to complete that task and remove it from the list.
However, a bug can be triggered in that flow by: Link is to my example app on StreamlitâŠshould be publicly available?
Place text in the text_input field
Click on any available checkbox in the list above
Doing so will cause the selected task to be completed (yes) AND a new task to be created (no). Additionally, and rightly so, youâll generate an error if you click 2, successive checkboxes with the same text sitting in the text_input widget.
So, at this point, and with your additional explanation, I can only assume that I need to use additional functionality to get autonomous operation out of the ability to enter textâŠsuch as a single element Form wrapping just that text_input box and setting the on_change for the submit button. I just find the default behavior of triggering solely off of loss of focus instead of a more concrete action like on_click to be moderately confusing.
Google Tasks also do not show a prompt to the user to âPress Enter to submitâ. This statement creates an expectation, to me at least, that it is the act of pressing the Enter key that performs the action/update.
None the lessâŠI think I have my answer(s) at this point whether I like 'em or not.
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking âAccept allâ, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.