I have two fields on a StreamLit page hosted in a Databricks App.
The user fills in values for these fields.
The first value is a unique key in a underlying table.
With values in these fields, the user can click a “Save” button, or a “New” button.
This question is about the actions behind the “Save” button.
On “Save” button click a query is triggered to see if the key value entered already exist in a table.
If if does already exist then a confirmation dialog is presented with a “Cancel” button and a “Overwrite” button.
The intent is that “Cancel” returns the user back to the original page nothing else done.
But if the user click “Overwrite” then the values are written to the table (updating the value of the second field of the table given the associated key).
However. The confirmation dialog presents on screen then immediately disappears without the user having an opportunity to click their “Cancel” / “Overwrite” option because, in code, you have to get a “st.rerun()” to resolve the dialog. But st.rerun() also means the confirmation dialog is not going to wait for the user.
Thanking you in advance.
The following is a mock up:
import streamlit as st
def overwrite_warning():
st.warning("overwrite warning")
btn_cncl, btn_ovwt, blkspc = st.columns([0.2, 0.3, 0.5])
with btn_cncl:
cncl = st.button("Cancel")
with btn_ovwt:
ovwt = st.button("Overwrite")
if cncl:
return('CancelDontSave')
if ovwt:
return('OkayToOverwrite')
return(None)
@st.dialog('zz_dialogtest')
def my_dialog():
r = overwrite_warning()
return(r)
def btn_save_process(process_name, process_desc):
e = True if process_name == 'steve' else False
if e:
r = str(my_dialog()) # "None" / "CancelDontSave" / "OkayToOverwrite"
if r == 'OkayToOverwrite':
st.write('upsert to the table')
pn = st.text_input("Process Name", value= "steve")
pd = st.text_input("Process desc", value= "")
if st.button("Save"):
btn_save_process(pn, pd)
st.rerun()
Looking at your code, I can identify exactly why your confirmation dialog appears and immediately disappears:
if st.button("Save"):
btn_save_process(pn, pd)
st.rerun() # <-- This is the problem
What’s happening:
User clicks “Save” button
btn_save_process() runs and calls my_dialog() to display your confirmation dialog
But before the user can interact, the very next line st.rerun() executes
This forces Streamlit to reload the entire app, causing the dialog to disappear
Simply remove the st.rerun() line.
In Streamlit, button clicks already trigger a rerun automatically, so your explicit st.rerun() is causing a second unwanted rerun that’s interrupting the dialog.
Without that line, the workflow will be:
User clicks “Save” → dialog appears
User clicks “Cancel” or “Overwrite” → those buttons trigger their own natural rerun
During that rerun, your code can process the dialog result as expected
No additional state management is needed for this specific issue - just remove the problematic rerun.
Tinkering with my mock up this morning I found you are correct.
But there is something in your remark to re-consider. I do not find “clicking a dialog the button automatically call rerun()”.
By remarking out the rerun() you are pointing to now the dialog now never goes away no matter how much button clicking you ezecute.
So if I remove the returns() from overwrite_warning() and add rerun() instead to each of if cncl & if ovwt then I get the expected/desired behavior.
This also implies I will now have to do everything else necessary for cancel opr overwrite before hitting either of these two new st.rerun()s.
After understanding your problem better, I found a solution to your problem:
import streamlit as st
# Initialize session state for storing dialog result
if 'dialog_result' not in st.session_state:
st.session_state.dialog_result = None
@st.dialog('zz_dialogtest')
def my_dialog():
st.warning("overwrite warning")
btn_cncl, btn_ovwt, blkspc = st.columns([0.2, 0.3, 0.5])
with btn_cncl:
cncl = st.button("Cancel")
with btn_ovwt:
ovwt = st.button("Overwrite")
if cncl:
st.session_state.dialog_result = 'CancelDontSave'
st.rerun()
if ovwt:
st.session_state.dialog_result = 'OkayToOverwrite'
st.rerun()
def btn_save_process(process_name, process_desc):
e = True if process_name == 'steve' else False
if e:
my_dialog() # "None" / "CancelDontSave" / "OkayToOverwrite"
if "dialog_result" in st.session_state and st.session_state.dialog_result is not None:
if st.session_state.dialog_result == 'OkayToOverwrite':
st.write('upsert to the table')
st.session_state.dialog_result = None
pn = st.text_input("Process Name", value= "steve")
pd = st.text_input("Process desc", value= "")
if st.button("Save"):
btn_save_process(pn, pd)
Why This Works
This solution works because of how Streamlit’s execution model handles state and reruns:
First run:
User clicks “Save”
Dialog appears
Script execution finishes
Second run (after user clicks “Overwrite” in dialog):
The if “dialog_result” in st.session_state… part runs and sees the stored value
“upsert to the table” message is displayed
Dialog result is reset for next use
The key insight is using session_state as a “memory” that persists between reruns, allowing the script to “remember” what happened in the dialog even though the script restarts.
Importantly, you’re not trying to capture the dialog’s return value directly (which would be impossible due to the rerun), but instead checking the stored session state value on the next run.
I like how your solution takes button click actions out of def my_dialog().
I have a feature in my end solution where I need to take actions in the script where you’re testing "dialog_result" in session_state.
Seeing what you’re presenting seems like it will go a long way to that end goal.
Thanks.
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.