Update slider value

Hey @posey22

Iā€™m having a hard time understanding your question, but I totally get that UI behavior is really hard to describe in words :laughing:

So for example, if I use a slider to choose a value that then multiplies a column in a dataframe when I press a button to submit that calculation, if I go to submit using a button somewhere else that gets reset. I would like the results of that button press to persist. In other words, I want that button value to stay True.

Weā€™ve actually been thinking about the ā€œsubmit buttonā€ scenario lately, and considering whether we should provide a new API just for this case. For example, maybe there should be a way to specify a ā€œwidget groupā€ whose values only get set to the server when ā€œsubmitā€ is pressed.

But to better design this API, it would be great to get a bunch of ā€œtoy examplesā€ of what people would like to do with it. So if you can come up with a tiny script that exemplifies what you need, that would be amazing!

Iā€™m assuming what youā€™re working on with SessionState fixes this issue?

Streamlit reruns your script fresh from the top every time you change the value of a widget. But sometimes you want to keep some values around in between runs (for example, when incrementing a variable, when doing incremental manipulations of a dataset, etc.).

Thatā€™s where SessionState comes in. It lets you persist data across reruns.

If I hit the button 5 times x will always be 1 if it started by 0.

Hmmmā€¦ thatā€™s not supposed to happen with the code snippet I pasted above. Did you try running it? Or perhaps youā€™re reacting to the API used for the SessionState prototype? In case itā€™s the latter, hereā€™s a quick explanation of how the prototype API works:

When you do this:

state = SessionState.get(x = 100)

if st.button('Increment x'):
    state.x += 1

st.write("Current value of x:", state.x)

Hereā€™s what happens behind the scenes:

  1. When a user opens a new browser tab with your Streamlit app, Streamlit runs the script above from top to bottom. When it reaches the SessionState.get() statement, it checks whether that given user already has a ā€œsessionā€ object associated with it. If not, then it initializes the state value of state.x to 100. Note that this only happens once per user!
  2. When the user clicks the ā€œIncrement xā€ button, Streamlit reruns your script from top to bottom. This time, the SessionState.get() statement will return that userā€™s existing SessionState object.
  3. Since the user clicked the button, the if condition will be True, so state.x will increment by 1 and st.write() will write ā€œCurrent value of x: 1ā€ to the app.
  4. If the user clicks ā€œIncrement xā€ again, Streamlit will rerun your script from top to bottom. Now SessionState.get() will return a state object where state.x is set to 1. So this time the code inside the if condition will increment it to 2.
    And so on!

Iā€™ve thought of it two ways, either the initialization step could be performed once, or the updated variable could be cached. I too am looking for this functionality.

As described above, your first idea is exactly what we do: the initialization step is only performed once :smiley:


This discussion is super valuable, by the way! It makes it clear that API of the SessionState prototype is not very clear. One way to improve it would be to rename the get() method to something like get_or_set or get_existing or something like that.

Also: with respect to buttons in general, in addition to the ā€œwidget groupā€ API I mentioned at the top, weā€™re also considering another API where buttons are allowed to run small callback functions before a script executes ā€” among other ideas. For more on this, check out this thread: How to evolve complex state (e.g., annotate data)?

1 Like