Search code examples
pythonpython-3.xfunctionstreamlit

Streamlit button on_click how to use it?


I've the following code

def drawBtn():
    option= ...
    st.button("Find", on_click= onSearch, args= [option])
    
def onSearch(opt):
    # do something and then...
    st.success("Done!")
    
drawBtn()

The problem here is that the message "Done" is insert at the top of the page instead of at the end. This problem appear only if i use on_click function. If i change it with if st.button(...): it work as i expect

Why using on_click function seems like moving the pointer of the page at the beginning?

Searching on the internet i saw always function that set only variables in st.session_state. So another question is: can I do something else inside a on_click function different to set session_state variables? Because If I try to add something else, that content is drawn always at the beginning of the page


Solution

  • Streamlit reruns your script on every interaction (like pressing the button). When you press the button, your entire script will be executed again but this time, st.button will return True, allowing you to do if st.button(...):, which executes the code in the if block right after the button appears.

    When you use on_click, the script will still be rerun. The function that you passed to on_click will be executed before the script, at the beginning of the run, not after the button. So, naturally, any element that you generate in that callback will appear before other elements, since they weren't regenerated in this run yet.

    Here is a link to a thread on Streamlit forums where this is discussed: link.

    Can I do something else inside a on_click function different to set session_state variables?

    Yes, you can use it to do anything. But it will run before anything else, you have to keep that in mind. If you don't want that, you can either use if st.button(...): instead or use it to set session state variables to trigger some conditional code in a different part of the script.

    Here is a nice use case for on_click: after pressing the button, we want something to appear before it. on_click is used to set the variable right away, before we even get to the button and notice that it returned True this time (You can use the key parameter of st.button to achieve a similar effect, creating a session state variable that you can use before you get to the button in this run).

    if "clicked" not in st.session_state:
        st.session_state["clicked"] = False
    
    def drawBtn():
        option= ...
        st.button("Find", on_click= onSearch, args= [option])
        
    def onSearch(opt):
        st.session_state["clicked"] = True
        
    if st.session_state["clicked"]:
        st.success("Done!")
    
    drawBtn()