How to apply a "lock all" function to session_state?

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,)

Thanks for any help, I really appreciate it :slight_smile:

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.

2 Likes

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

For example:

def my_func(x):
   st.write(x)

st.checkbox("Item 1", on_change=my_func, args=(1,))

st.checkbox("Item 2", on_change=my_func, args=(2,))
1 Like

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).

:magic_wand:

1 Like