Refreshing page on st.number_input or chaning st.text_input

Hello there. I use st.button that adds st.text_input, but everytime I write something into text_input and press enter, it refreshes the whole page. I saw the similar topics and advices to use session states, but I don’t quite understand how to use it.

Hi @Rockkley,

As you point out, many people as they transition to the more advanced session state features have trouble wrapping their minds around the workflow of callbacks. I actually wrote a Knowledge base article in our documentation to help with this exact scenario!

In the article, the button interacts with a slider, but the principle is the same. All you have to do is create and track a key:value pair when the button has been pressed, via the on_click parameter.

Then in your script, you use the value stored in state to display your text_input and process the rest of the app.

Happy Streamlit-ing!
Marisa

I tried to do it, but I don’t know why it keep refreshing. Can you provide an example of code, that goes like - you press button, it creates text_input, you write something in it, press enter and then your text from text_input appears on the screen somewhere? I honestly don’t understand why it needs some extra actions to stop it from refreshing. Thanks

Hi @Rockkley ,

If I understood you correctly, below is the code snippet . I tried to follow as you mentioned here,

import streamlit as st
# Session State initializing
if 'store' not in st.session_state:
    st.session_state.store = False 

# you press button, it creates text_input    
_opt = st.button("Press to eneter a text")

if _opt or st.session_state.store:
    st.session_state.store = True # Get's true the very first time
# you write something in it, press enter 
    input = st.text_input("you write something")
    
    if input:
        # and then your text from text_input appears on the screen somewhere
        st.write(input)

Best,
Avra

2 Likes

Thanks you alot, Avra. But I still can’t figure it out when trying to use it in my code. I would really appreciate if you would find time to look at it and help me with the solution:

How should it work - You guess a two-digit number, then press button. Then you see three bot’s guesses appear on the screen, with a number_input under it. In the number_input you write the number that was in your mind before you pressed the button, and if it matches any of bot’s guesses, then it edit’s their reputation that also shown on the screen. My problem with this scenario is in the step of writing the number into number_input - after number_input appears, it momentaly takes the default value of it (10 as I set it as min.value) and no matter what I write after that - the page just reloads partly. I tried to add “st.session_state.store = True” in different places of the code but it didn’t help. Sorry my english and I hope you understand what I mean. Thanks alot again anyway

Hey @Rockkley,

What do you mean by this? When I tested your code it works just as (I think) you want it to, check out this screenshot is this was you were hoping for? :point_down:

Happy Streamlit-ing!
Marisa

Thanks for the feedback Marisa! What I mean by “partly” is - the lists before the button (bot guesses history) keeps updating and saves the data just how I wanted it to work. But there is a problem:
If after pressing the button you got, for example, zero - 30, one - 11, two - 67, and you write “11” in the number_input, the first three lines (bots points) should be updated like this - zero “-1”, one “1”, two “-1”, - the bot who guessed your number right gets one point, other two gets minus one point each. And the page should reload every time after you press “enter” after writing a number in number_input.
What happens when I run my code:
no matter what I write in number_input, seems like it only reads the default “10”, because if at least one of three bots says “10”, it gets a point. In all the other cases (no matter what number I write) they all getting minus one point. Is it different when you run it?

I have updated my code, so now it shows a list of numbers you wrote in number_input (after the first time). I can’t get anything but “10,10,10,10…”

Hey @Rockkley ,

My results are similar to Marisa’s @Marisa_Smith and I assume that’s what you expected right?
I’m bit lost in your code, however, I can guess the origin of this result :arrow_down: ,

This is because of the if block,

 if input:   
        st.session_state.usersnumbs.append(input)

Based on the logical statement used, your code runs with the initial value, and stores it .
I would debug this case study, with more structured code blocks and dump the output with streamlit syntaxes. For example in the last if block - if 0 added as minimum value of st.number_input, the result won’t display the minimum value always, since the code does not satisfy the if condition.

Goodluck,
Avra

Thanks you for your attention.
I’m not sure I understand what you mean. Should I use on_change attribute of number_input? I tried but didn’t figured out how to do it. Or what else? Sorry for being nooby, if it is so.

I mean, what should I do to make it store the number that I’m writing in number_input, not the default number? (keeping min and max)

Hey @Rockkley!

Thanks for the extra detail on that, I understand where you were getting issues! I actually fixed your code for you and put in a pull request to your repo to fix the flow of the app!

So what was happening is that because when the app runs and the number_input is added to the screen your app was counting that as if the user picked that number.

But they haven’t yet! So I added a key:value pair in state to track if the user has actually interacted with the number_input, or if the app was just running the calculations. I edit this key:value pair in a call back from the number input I called num_selected.

Then on line 99 i changed the logic in your app to use this parameter to run your logic on scoring the computer guesses of the number. at the end of this (line 123) I reset the user_select value to False. after your app is finished processing the scores!

Now, when your app runs, it only updates the usersnumbs list when a person has actually entered the number in the number_input, and not when your app is processing!

All you have to do is accept my pull request, and your code will update! :two_hearts:

Happy Streamlit-ing!
Marisa

1 Like

I’m lost for words to say how thankful I’m for your time and your feedback!
It really describes the quality of the development process on Streamlit to me. I will study Streamlit and keep track of updates.
However… I’m new to Github, and maybe I did something wrong, but I pressed “Merge” on your request, and now the code works even worse than before. I tried to partly copy your added code, but it didn’t help. I bet I messed it up somehow, I’m sorry, I don’t know what to do with it

1 Like

Hey @Rockkley,

can you screen record the behaviour of your app? and also tell me what version of Streamlit you are using, what package manager, and the terminal command you are using to run your code?

Are you trying to run your code via pycharm? like you said in your other topic?

Streamlit 1.3.1, PyCharm. Installed by “pip” and in with “Python packages” in PyCharm.

Here’s the video: streamlit trbls - YouTube

Hey @Rockkley,

Ok, I think it’s because of the way your app is running. It’s written in a way that I think is making it more difficult than it needs to be. Here are my suggestions:

  • rearrange your app so that the number input comes up first, the person enters their number
  • the computer guesses 3 random numbers and prints them to the screen
  • you calculate if any of the guesses match the number the person entered, and score them accordingly
  • print the score of each

here is a mini-app that does this and works just as you expect, the scores update and everything:

import streamlit as st
import random

st.title("App that guesses numbers")

if "points_1" not in st.session_state:
    # points for guesses
    st.session_state.points_1 = 0
    st.session_state.points_2 = 0
    st.session_state.points_3 = 0

with st.form("user_number"):
    num = st.number_input("Enter your number", min_value=10,max_value=99)
    submit = st.form_submit_button("Submit your number")

if submit:
    guess_1 = random.randint(10,100)
    guess_2 = random.randint(10,100)
    guess_3 = random.randint(10,100)

    if num == guess_1:
        # guesser 1 is correct
        st.session_state.points_1 += 1
        st.session_state.points_2 -= 1
        st.session_state.points_3 -= 1
    elif num == guess_2:
        # guesser 2 is correct
        st.session_state.points_1 -= 1
        st.session_state.points_2 += 1
        st.session_state.points_3 -= 1
    elif num == guess_3:
        #guesser 3 is correct
        st.session_state.points_1 -= 1
        st.session_state.points_2 -= 1
        st.session_state.points_3 += 1
    else:
        # all wrong
        st.session_state.points_1 -= 1
        st.session_state.points_2 -= 1
        st.session_state.points_3 -= 1

    st.write("Your selected number:", num)
    st.write("Computer guess #1",guess_1, "Score:", st.session_state.points_1)
    st.write("Computer guess #2",guess_2,"Score:", st.session_state.points_2)
    st.write("Computer guess #3",guess_3,"Score:", st.session_state.points_3)

Happy Streamlit-ing!
Marisa

Thanks you alot once again, Marisa. But I need my app to work exactly the way it is now - first you get bot’s numbers, then you enter your number.