Summary
What I am trying to achieve: When the app loads, a default directory path will be stored in the session_state
. A text_input
box should display the current directory when the app loads. This should be editable (like when value
is used instead of placeholder
). The user should be able to edit the directory path and upon hitting enter, the current directory will be stored and used based on the user input.
Steps to reproduce
I am having issues getting the exact behavior I am looking for. I can either get it so that I use a value but the session state variable used to store the current directory needs to be updated twice sometimes (issue 1), I just use a placeholder which works but the text is not editable (issue 2), or I use a key and value, which gives me the warning (issue 3). I know the warning only loads once when the app is launched, but it is not something I want users to see every time they launch the app.
Issue 1
The directory entered needs to be entered twice in order for session_state.current_directory
to be updated. Similar post (Streamlit: Form Button has to be clicked twice).
Code snippet:
import streamlit as st
state = st.session_state
def change_directory():
if state.current_directory != state.updated_directory:
state.current_directory = state.updated_directory
if "current_directory" not in state:
state.current_directory = "D:/default_directory"
if "updated_directory" not in state:
state.updated_directory = ""
state.current_directory = st.text_input("Enter a directory (issue 1)", value=state.current_directory)
st.write(state.current_directory)
# state.updated_directory = st.text_input("Enter a directory (issue 1)", value=state.current_directory)
# change_directory()
# st.write(state.current_directory)
Here are the two ways I attempted. Comment out and uncomment the relevant lines of code to see the other way I tried. In both cases, this will work the first time a new directory is entered. Upon hitting enter, the value updates. However, every time after, you must enter a directory twice in order for the value to be updated. Oddly, when you have to enter it twice, the first attempt that does not work is disregarded. I do not understand how exactly Streamlit executes the code so it is very weird that for every pair of values entered, the first one does nothing, and the second one correctly updates the value.
Issue 2
Using placeholder
will show the value of the directory, but is not editable. This is an issue because the directory paths could be very long and if for instance, a user has different folders they want to switch between where the paths are something like “D:/base directory/subdirectory/by month/january” , “D:/base directory/subdirectory/by month/february”, etc… having to type the full directory path is not ideal. I want the path to be editable, so they can just change the month name.
Code snippet:
import streamlit as st
state = st.session_state
def change_directory():
if state.current_directory != state.updated_directory:
state.current_directory = state.updated_directory
if "current_directory" not in state:
state.current_directory = "D:/default_directory"
if "updated_directory" not in state:
state.updated_directory = ""
st.text_input("Enter a directory (issue 2)", key="updated_directory", placeholder=state.current_directory, on_change=change_directory)
st.write(state.current_directory)
This works for only needing to enter the new directory once, but the placeholder value is greyed out and not editable.
Issue 3
Using a key
and value
gets closer to the desired behavior. This will solve both issues 1 and 2. However, it is not perfect. I know Streamlit does not suggest using a key
and value
, since a warning will show once the app is loaded. This is not ideal since the user might think there is a bug in the app. This also doesn’t quite solve the issues I’m having because the initial directory shown will be blank. After a user enters a new directory once, the text will show and will be editable. But when the app is launched, the default directory will not show. Using a placeholder
can fix that, but the default directory is not editable and only after it is changed once it will be, which is not ideal for the user.
Code snippet:
import streamlit as st
state = st.session_state
def change_directory():
if state.current_directory != state.updated_directory:
state.current_directory = state.updated_directory
if "current_directory" not in state:
state.current_directory = "D:/default_directory"
if "updated_directory" not in state:
state.updated_directory = ""
st.text_input("Enter a directory (issue 3)", key="updated_directory", placeholder=state.current_directory, value=state.current_directory, on_change=change_directory)
st.write(state.current_directory)
Expected behavior:
I would like a user to be able to launch the app with no warning, have a text_input
with a default directory displayed that is editable, and each time they edit/change the directory, the current directory updates correctly.
Actual behavior:
See above.
Debug info
- Streamlit version: 1.19.0
- Python version: 3.9.12
- Using venv
- OS version: Microsoft Windows 11 Home 10.0.22621 Build 22621
- Browser version: Chrome Version 110.0.5481.178 (Official Build) (64-bit)
Requirements file
streamlit
omegaconf
Pillow