Text_area saving after timeout and automatic switch page

Hi,

i want to setup a questionar page with a automatic switch the page after a timeout. the switch_page worked very well, but the text_area will only be safed if it is not activ. If it is active the safed text ist None.
I try to apply crtl+enter befor switch_page but it seems that it would not taken.

Here are my app:

# -*- coding: utf-8 -*-
"""
Spyder Editor

This is a temporary script file.
"""

import streamlit as st
import time
from datetime import timedelta

from streamlit.components.v1 import html

if 'end' not in st.session_state:
     st.session_state.end = time.time() + 10

def add_clock(length: timedelta = timedelta(minutes=0, seconds=0)):
    num_seconds = length.total_seconds()
    html(
        """
    <div id="clockdiv">
    <div>
        <span class="minutes"></span>
        <div class="smalltext">Minutes</div>
    </div>
    <div>
        <span class="seconds"></span>
        <div class="smalltext">Seconds</div>
    </div>
    </div>
    <script>
    function getTimeRemaining(endtime) {
    const total = Date.parse(endtime) - Date.parse(new Date());
    const seconds = Math.floor((total / 1000) % 60);
    const minutes = Math.floor((total / 1000 / 60) % 60);

    return {
        total,
        minutes,
        seconds
    };
    }

    function initializeClock(id, endtime) {
    const clock = document.getElementById(id);
    const minutesSpan = clock.querySelector('.minutes');
    const secondsSpan = clock.querySelector('.seconds');

    function updateClock() {
        const t = getTimeRemaining(endtime);

        minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
        secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);

        if (t.total <= 0) {
        clearInterval(timeinterval);

        var simulatedEvent_ctrl_enter = new KeyboardEvent('keypress', {
         "key": "Enter",
         "keyCode": 13,
         "which": 13,
         "code": "Enter",
         "altKey": false,
         "ctrlKey": true,
         "metaKey": true,
         "shiftKey": false,
         bubbles: true,
         cancelBubble: false,
         cancelable: true,
        });
        parent.document.getElementsByClassName('st-key-note_vignette_1')[0].children[0].children[1].children[0].children[0].dispatchEvent(simulatedEvent_ctrl_enter)
        
        const streamlitDoc = window.parent.document;
        streamlitDoc.dispatchEvent(simulatedEvent_ctrl_enter);

        const buttons = Array.from(streamlitDoc.querySelectorAll('.stButton > button'));        
        const weiter_button = buttons.find(el => el.innerText === 'Weiter');        
        weiter_button.click();
        }
    }

    updateClock();
    const timeinterval = setInterval(updateClock, 1000);
    }
    """
        + f"const deadline = new Date(Date.parse(new Date()) + {num_seconds} * 1000);"
        + """
    initializeClock('clockdiv', deadline);
    </script>
    <style>
    body{
    text-align: center;
    background: #00ECB9;
    font-family: sans-serif;
    font-weight: 100;
    }

    #clockdiv{
    font-family: sans-serif;
    color: #fff;
    display: inline-block;
    font-weight: 100;
    text-align: center;
    font-size: 30px;
    }

    #clockdiv > div{
    padding: 10px;
    border-radius: 3px;
    background: #00BF96;
    display: inline-block;
    }

    #clockdiv div > span{
    padding: 15px;
    border-radius: 3px;
    background: #00816A;
    display: inline-block;
    }

    .smalltext{
    padding-top: 5px;
    font-size: 16px;
    }

    #start{
    display: block !important;
    margin-top: 10px;
    cursor: pointer;
    }
    </style>
    """,
        height=100,
    )


add_clock(timedelta(seconds=10))

st.progress(12)


# Vignette 1
st.subheader("Vignette 1:")
st.info("FĂĽr die Bearbeitung der Aufgabe haben Sie 10 Minuten Zeit.")

st.write("Sehen Sie sich nun die Videovignette an und beobachten Sie die Szene aufmerksam. Bearbeiten Sie anschließend folgende Aufgaben. Sie haben die Möglichkeit bei Bedarf das Video zu stoppen oder auch Teile erneut anzusehen.")

st.video(r"\.spyder-py3\vignette1.mp4")

   
note_vignette_1 = st.text_area('Beschreiben Sie welche Aspekte des Verhaltens der SchĂĽlerinnen Ihnen in der gezeigten Unterrichtssequenz aufgefallen sind.', key='note_vignette_1')
switch_page_botton = st.button(label = "Weiter", key= "weiter-button")
   
if switch_page_botton:
    f = open("note_vignette_1.txt", "w")
    f.write(note_vignette_1)
    f.close()
    st.switch_page("./pages/1_vignette2.py")

Thanks

As far as I know, this is expected in a way… There isn’t a way to deal with it through supported mechanisms. A widget value is not submitted to the back end until the user focuses out of it or uses a keyboard shortcut to submit it (like Ctrl+Enter). So if you programmatically switch the page while someone is typing, the pending value is not known by the server.

I submitted an issue on GitHub for the engineers to review even though I’m not sure it’s technically a bug. It’s potentially unintuitive. Pending changes to a widget are not submitted if interrupted by `st.rerun()` or `st.switch_page()`. · Issue #10169 · streamlit/streamlit · GitHub

1 Like

It seems for me also that its a lack between browser input and streamlit app. I try to apply a crtl+enter javascript keyboardevent but it did not change something.