Argument handling unclear

Hi,

when having a form when submit button clicked, args are handed over after second click only.

Taken a simple form

with st.form(key='Zählerdaten', clear_on_submit=True):
        add_strom = st.number_input('Strom', )
        add_gas = st.number_input('Gas')
        add_wasser = st.number_input('Wasser')
        # Every form must have a submit button.
        submitted = st.form_submit_button("Speichern", 
                                on_click=add_measurement, 
                                args=(add_strom, add_gas, add_wasser, df),
                                kwargs=None)
def add_measurement(add_strom, add_gas, add_wasser, df):
    new_data = {'Strom': add_strom, 'Gas': add_gas, 'Wasser': add_wasser}
    st.write(new_data)

args values are displayed only after a second click on submit button

Looks like the callback is receiving the previous value of the widget, not the current one. Do you really need a callback here? The more straightforward method works as expected.

import streamlit as st


with st.form(key="form", clear_on_submit=True):
    number = st.number_input("Number")
    submitted = st.form_submit_button("Submit")

if submitted:
    st.write(number)

…no, the alternative you proposed would work as well.
Nevertheless the method does some more data updates in the background, therefore it seems to be straight forward couple the method to a click event.

Looks like the callback is receiving the previous value of the widget

This is the reason why I raised it up here. I would like to understand if it works as expected (and then why only the previous value is handed over) or if we have a bug here.

Hi, as mentioned on another post, you should use session state and keys for the inputs.
The code below does as you like and is simpler:

import streamlit as st

def add_measurement():
    new_data = {'Strom': st.session_state.add_strom, 'Gas': st.session_state.add_gas, 'Wasser': st.session_state.add_wasser}
    st.write(new_data)

with st.form(key='Zählerdaten', clear_on_submit=True):
        st.number_input('Strom', key = "add_strom")
        st.number_input('Gas', key = "add_gas")
        st.number_input('Wasser', key = "add_wasser")
        submitted = st.form_submit_button("Speichern", 
                                on_click=add_measurement)`

The working app is here

1 Like

thank you, I already tested it successfully.

Nevertheless, the form_submit_button does not work with args as expected. Should I repot it as a bug?

It’s not a bug I don’t think, but it’s not clearly explained in the documentation.

Basically, the variables in the select aren’t written to the variable names until you choose an option from the drop-down, but the callback is also executed on change and appears to run first.
That’s why we have to use the widget key in the callback function.

Definitely could be made clearer in the docs with another example or two, but using keys is a nice solution

Edit: seems there is some discussion/documentation around this

1 Like