A button to open a form

I would like to have (several) buttons for each there is a form with submit button.
use case example: button will be “add user” and the form will be “username” and “password” + submit.
When I try a naive implementation it does not work properly (see snippet, it’s hard to explain but basically values are not updated and seems like nothing happens)

Would appreciate help.

import streamlit as st

x = 5
y = 3

if st.button('press here to edit'):
    with st.form('form'):
        new_x = st.text_input('edit the value', x)
        new_y = st.text_input('edit the value', y)
        if st.form_submit_button('submit'):
            x = new_x
            y = new_y
            st.success('updated successfully')
        if st.form_submit_button('cancel'):
            st.warning('cancelled')
st.text(f'{x},{y}')
1 Like

Hi @Hanan_Shteingart1 ,

Trust you are good. I just came across your issue here on streamlit.

I just did some update on your code by applying session state, i realize your app keep rerunning on a single session. so I partitioned the session to allow other buttons, Buttons will naturally rerun your session.

Kindly check with this code;

import streamlit as st

x = 5
y = 3
def is_user_active():
    if 'user_active' in st.session_state.keys() and st.session_state['user_active']:
        return True
    else:
        return False
# if st.button('press here to edit'):
if is_user_active():
    with st.form('form'):
        new_x = st.text_input('edit the value', x)
        new_y = st.text_input('edit the value', y)
        if st.form_submit_button('submit'):
            x = new_x
            y = new_y
        st.text(f'{x},{y}')
        #You can as well save your user input to a database and access later(sqliteDB will be nice)
        st.success('updated successfully')
        if st.form_submit_button('cancel'):
            st.warning('cancelled')
        
        st.info("Kindly reload your browser to start again!!!!")
else:
    if st.button('press here to edit'):
        st.session_state['user_active']=True
        st.experimental_rerun()

Do not forget to mark this as SOLUTION if it solve your problem… Great to see you streamliting. :v: :v:
:smiley:

Thanks you for your contribution.

Yet your solution is kind of cumbersome and asks the user to reload the page. It also does not scale. I have many buttons and each opens a different form. I am looking for something cleaner.

I guess session state is the way to go.

Buttons and forms have strange behavior. It’s not clear when callback is needed and when just an if statement is enough.

1 Like

Okay.

I will continue to check for alternative approach and share once i get it

1 Like

@Hanan_Shteingart1 Don’t have an immediate solution for you but do you think toggle buttons would be a solution to your problem?

I.e. a button that works like a toggle. You can click it once, then its state is clicked / it returns True (no matter if Streamlit reruns) and if you click it again, it switches to unclicked / returns False. I imagine you could have different toggle buttons in your app then and depending on which one is clicked, you can show the correct form.

1 Like