Check if dialog is open, and close the dialog manually

Is it possible to check whether any dialog is currently open?

My use case is this:

async def async_task(user_input):
    await asyncio.sleep(100)
    return "Result: " + user_input

user_input = st.text_input("Your input here")
if st.button("Run job"):
    @st.experimental_dialog("Received", width="small")
    def show_received_dialog():
        with st.container(border=False, height=150):
            st.write("Received: " + user_input)
    show_received_dialog()

    result = asyncio.run(async_task())

    ## sample code here
    # if st.is_dialog_open():
    #    st.close_dialog()

    @st.experimental_dialog("Completed", width="small")
    def show_completed_dialog():
        with st.container(border=False, height=150):
            st.write("Thanks for waiting!")
            st.write(result)
    show_completed_dialog()

Right now it is throwing an error that I cannot run multiple dialogues together.

I am not sure if you know when the dialog is close.
If thing the best is to add a second st.button().
You can “hide” it inside the dialog

        st.session_state.user_input = st.text_input("Enter your input:", "")
        if st.button("Run job"):
            st.session_state.dialog_step = 1

        if 'dialog_step' not in st.session_state:
            st.session_state.dialog_step = 0

            # Dialog function to show the first dialog
        @st.experimental_dialog("Task Progress", width="small")
        def show_progress_dialog():
            st.write("Received: " + st.session_state.user_input)
            if st.button("Next"):
                st.session_state.dialog_step = 2
                st.rerun()

        # Dialog function to show the second dialog
        @st.experimental_dialog("Task Progress", width="small")
        def show_progress_dialog2():
            st.write("⏳ Thanks for waiting!")
            if st.button("Close"):
                st.session_state.dialog_step = 3  # Or reset to 1 if you want to start over
                st.rerun()
        # Show dialogs based on the current step
        if st.session_state.dialog_step == 1:
            show_progress_dialog()
        elif st.session_state.dialog_step == 2:
            show_progress_dialog2()


Thanks for the solution, but I’m not too sure where the async task will fall in here. If I place it within “Next”, it will not trigger if the user exits the dialog without clicking next.
If I place it before the “Next” button, it will run and wait for the task to complete, before “Next” can be clicked.
In fact, the users should not need to click a “Next” button as I intend it to be a notification, not a step to be completed.

The reason why I want to make it a dialog is because a st.toast is too small and easily missed by my users, and they will ask me “why is it not running?”

Few solution here, you can make a spinner, we see it’s loading. There is some nice spinner you can add :
(GitHub - andfanilo/streamlit-lottie: Streamlit component to render Lottie animations by @andfanilo)

I am not sure a double pop-up windows to notice the user is the best approach.

        import asyncio

        async def async_task(user_input):
            await asyncio.sleep(10)
            return "Result: " + user_input

        user_input = st.text_input("Your input here")
        if st.button("Run job"):
            with st.spinner('Loading...'):
                result = asyncio.run(async_task(user_input))
            st.write(result)

with lottie_spinner

 import asyncio
        def load_lottiefile(filepath: str):
            with open(filepath, "r") as f:
                return json.load(f)

        lottie_path = r'PATHTOJSON.json'
        self.lottie_spinner = load_lottiefile(lottie_path)

        async def async_task(user_input):
            await asyncio.sleep(10)
            return "Result: " + user_input

        user_input = st.text_input("Your input here")
        if st.button("Run job"):
            with st_lottie_spinner(self.lottie_spinner, key=f"spinner", height=100):
                result = asyncio.run(async_task(user_input))
            st.write(result)

Hi @Faltawer, thanks for the reply.

At first, I have already a st.progress() running, and also have tried using stqdm as well. The issue is that my page is quite long, and the user won’t really scroll to the progress bar portion.