I’m developing a kind of survey using st.radio button inside a form. When I use the on_click function callback parameter of the submit button it always returns the default option and not the option that the user clicks.
Callback arguments are compiled at the moment their associated widget or button is rendered (not at the point they are called on click/change). I haven’t used exactly this configuration before, so unless there is some other issue with your data structure, my guess is that the self at the time the submit button is rendered is getting compiled into the callback function so you aren’t ever going to see new submission results.
You will need to assign keys to the widgets inside the form and then get their values from session state inside of the callback function instead.
This works for me:
import streamlit as st
class form_element():
def __init__(self, question, options, answer, key):
self.question = question
self.answer = answer
self.options = options
self.key = key
def check(self):
if st.session_state[self.key] == self.answer:
st.success('Correct!')
else:
st.error('Incorrect.')
def quiz(self):
with st.form(key='form'+self.key):
st.write(self.question)
st.radio('Answer',self.options, key = self.key)
st.form_submit_button('Submit', on_click=self.check)
my_form = form_element('Which comes first in the alphabet?', ['K', 'W', 'A', 'P'], 'A', 'question1')
my_form.quiz()
I actually realized that I wasn’t using a “st.session_state” for the random function that randomizes the options. After organizing and cleaning up the code, I found a thread by Marisa_Smith explaining how to get around this and it worked! I’m cracking my head trying to understand the linear way Streamit works compared to pyQt which works in a loop/wait mode.
I really thought that the callback arguments were only called the moment the widget or button was clicked or changed. Thanks for explaining.
The callback functions are executed when clicked, yes, but at least for their arguments args I know for sure that their values are “pulled” at the point the widget loads. So if you had had some args=self.property than the lookup of that value would have happened when the button rendered and not seen a new value had it been changed in any way before the button was clicked.
This is a common confusion that comes up with forms. I was only taking a guess that there might have been some impact on the function via a similar construct since you were using self, but maybe that wasn’t the case. As I said, I had never tried structuring a form inside a class like that, so I just tried something I thought would work. Indeed, if you have some random generation and you want to continue to work with it, you’d need to store the output into session state and make sure to not keep changing it with each page load. If fixing the random generation was all you needed, then great, the use of self didn’t actually throw an extra hiccup into the mix.
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.