I see the difficulties in achieving the goal of this sample code. One is the use of variables and two is the clearing of the value (ui-wise) of the text input widget.
There are two methods to get the value of a widget such as text input widget.
- Get the return value
input_text_1 = st.text_input("input_text_1", key="input_text_1")
print(input_text)
- Get the value via the key of the widget using session state.
st.text_input("input_text_1", key="input_text_1")
print(st.session_state.input_text_1)
For example,
def create_config_mapping(df, account, input_text_1,
dropdown1, dropdown2, input_text_2, bool1, bool2):
key = f"{dropdown1}_{dropdown2}"
payload['account'] = f"{account}"
payload['input_text_1'] = f"{input_text_1}"
payload['dropdown1'] = f"{dropdown1}"
payload['dropdown2'] = f"{dropdown2}"
payload['bool1'] = bool1
payload['bool2'] = bool2
The parameters input_text_1
, etc, is not necessary if you are using method 2. You can just use,
payload['input_text_1'] = st.session_state.input_text_1
And remove that parameter.
def create_config_mapping(df, account,
dropdown1, dropdown2, input_text_2, bool1, bool2):
You can do the same for other similar parameters.
Method 2 is superior as you can use the value anywhere. It also eliminates a single variable creation as in method 1.
Clearing the value in the text input widget may not be that clear. We will have to create a fresh widget by changing its key.
st.text_input("input_text_1", key="input_text_1")
Now if we type “test” in that widget, we cannot reset it to empty or “” unless we delete the value of the widget manually on the actual widget.
Programmatically to clear that widget value, we have to create a different key.
st.text_input("input_text_1", key="input_text_1_gtu")
This is the new key, input_text_1_gtu
.
But there is an issue on this, because we cannot always use input_text_1_gtu`.
The solution is to create a random key so that if the call is a success
we will create a new text input widget with empty value. For this we will use the uuid module of python.
We need to make the key of the widget a variable and create a new key only if response is successful because we are clearing the value of the widget.
Example:
import uuid
# make sure that `input_text_1_k` is not in session state.
if 'input_text_1_k' not in st.session_state:
st.session_state.input_text_1_k = str(uuid.uuid4())
st.text_input("input_text_1", key=st.session_state.input_text_1_k)
The key is a variable.
Other changes:
- Remove the submit callback function as everything are updated under the
button
if condition.
if st.button("Submit", key='button_submit'):
if selected_option is not None:
selected_slug = accounts[accounts['name'] == selected_option]['slug'].values[0]
if all([st.session_state[st.session_state.input_text_1_k],
dropdown1, dropdown2]):
formatted_global_df = format_global_df_mappings(global_mappings)
response = create_config_mapping(formatted_global_df,
selected_slug,
dropdown1, dropdown2, bool1, bool2)
...
- Create new random keys if response is sucessful. Also rerun to update the ui with latest states.
if response == 'success':
st.success("Mapping created successfully!")
time.sleep(1) # see the success message for 1 sec
# Clear the text input widgets by creating new keys.
st.session_state.input_text_1_k = str(uuid.uuid4())
st.session_state.input_text_2_k = str(uuid.uuid4())
# Reruns to update the ui.
st.rerun()
- In the condition:
if all([st.session_state[st.session_state.input_text_1_k],
dropdown1, dropdown2]):
The st.session_state.input_text_1_k
is the key of the widget. It is a variable so that we can clear its value. The value of this widget is: st.session_state[st.session_state.input_text_1_k]
Complete code
import uuid
import time
import streamlit as st
import pandas as pd
st.set_page_config(layout='centered')
# Define the variables for the text input widget keys.
# Make sure that the keys we are creating are not existing in the session state.
if 'input_text_1_k' not in st.session_state:
st.session_state.input_text_1_k = str(uuid.uuid4())
if 'input_text_2_k' not in st.session_state:
st.session_state.input_text_2_k = str(uuid.uuid4())
payload = {}
def format_global_df_mappings(global_df):
global_df['key'] = global_df['ColumnA'] + '_' + global_df['ColumnB']
return global_df
def create_config_mapping(df, account, dropdown1, dropdown2, bool1, bool2):
key = f"{dropdown1}_{dropdown2}"
payload['account'] = f"{account}"
payload['input_text_1'] = st.session_state[st.session_state.input_text_1_k]
payload['dropdown1'] = f"{dropdown1}"
payload['dropdown2'] = f"{dropdown2}"
payload['bool1'] = bool1
payload['bool2'] = bool2
if not df['key'].str.contains(key, case=False, na=False).any():
if st.session_state[st.session_state.input_text_2_k]:
payload["input_text_2"] = st.session_state[st.session_state.input_text_2_k]
# response = requests.post(url, json=payload, headers=headers)
# return response.text
return 'success'
else:
return 'input_text_2 required'
else:
# response = requests.post(url, json=payload, headers=headers)
# return response.text
return 'success'
df = pd.DataFrame({
'dropdown1': ['AA', 'AA', 'BB', 'BB', 'CC', 'DD'],
'dropdown2': ['11', '22', '11', '33', '44', '55']
})
global_mappings = pd.DataFrame({
'ColumnA': ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'],
'ColumnB': ['Apricot', 'Blueberry', 'Cranberry', 'Dragonfruit', 'Fig']
})
grouped_dropdowns = df.groupby('dropdown1')['dropdown2'].apply(list).to_dict()
accounts = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
'slug': ['alice', 'bob', 'charlie', 'david', 'eve']}
)
selected_option = st.selectbox("Account:", accounts['name'],
index=None, placeholder="Please Select an Account")
create_checkbox= st.checkbox("Create Check Box", key='create_checkbox')
# if 'input_text_1' or 'input_text_2' not in st.session_state:
# st.session_state.input = ''
# if 'area' not in st.session_state:
# st.session_state.area = ''
if create_checkbox:
col1, col2, col3, col4 = st.columns(4)
with col1:
st.text_input("input_text_1", key=st.session_state.input_text_1_k)
with col2:
dropdown1 = st.selectbox('Select dropdown1', list(grouped_dropdowns.keys()),
key='dropdown1')
with col3:
if dropdown1:
st.session_state.selected_dropdown1 = dropdown1
dropdown2 = st.selectbox('Select Service Level',
grouped_dropdowns [dropdown1],
key='dropdown2')
# if dropdown2:
# st.session_state.selected_dropdown2 = dropdown2
with col4:
st.text_input("input_text_2", key=st.session_state.input_text_2_k)
bool1 = st.checkbox("B1", key='b1')
bool2 = st.checkbox("B2", key='b2')
if st.button("Submit", key='button_submit'):
if selected_option is not None:
selected_slug = accounts[accounts['name'] == selected_option]['slug'].values[0]
if all([st.session_state[st.session_state.input_text_1_k],
dropdown1, dropdown2]):
formatted_global_df = format_global_df_mappings(global_mappings)
response = create_config_mapping(formatted_global_df,
selected_slug,
dropdown1, dropdown2, bool1, bool2)
if response == 'input_text_2 required':
st.error("input_text_2 is required. A Global Mapping was not found.")
if response == 'success':
st.success("Mapping created successfully!")
time.sleep(1) # see the success message for 1 sec
# Clear the text input widgets by creating new keys.
st.session_state.input_text_1_k = str(uuid.uuid4())
st.session_state.input_text_2_k = str(uuid.uuid4())
# Reruns to update the ui.
st.rerun()
else:
st.error("Please fill in all text inputs.")
else:
st.error("Please select an account from the dropdown.")
Sample output
Note in the function:
def create_config_mapping(df, account,
dropdown1, dropdown2, bool1, bool2):
You can remove dropdown1, dropdown2, bool1, and bool2 in the parameter. Inside this function, you can use st.session_state.dropdown1
and similar.