Stramlit App with API call and on_change within a form

Hey,
i am new to programming at all and struggeling with my first App that will be deployed in my companies App platform.
The App i try to write should collect required inputs regarding a new employee and when submit button is pressed send an email to all persons that need to know about the new employee.
What i want now is a text.input field (or any similar) where the person fills out the form starts to type into the field “responsible Person” and “Pate” and while typing there is an on_change LDAP API call to get all possible matches of all matches in LDAP. The User can now click on the right person from the suggested list and this person is now in the appropiate field. The LDAP api call returns name and email of the person so the email of the selected person should be automatically added to the list of mail receipients.
I’m struggeling with the on_change LDAP API call. Everything i tried failed and i did not find a solution by now. Does anybody have an idea or hint how to solve that?
Here is my code so far:

with st.form(key="my_form", enter_to_submit=False):
    user_name = get_name_from_ldap(user)
    st.title(
        f"Hallo {user_name}\nBitte gib hier, soweit vorhanden, alle Daten zum/r neuen Mitarbeiter/in ein."
    )
    c1, c2, c3 = st.columns(3, gap="small", vertical_alignment="center")
    with c1:
        option = st.selectbox(
            "Dienstverhältnis",
            (               
                "Auzubildende/r",
                "Dauerhafte/r Mitarbeiter/in",
            ),
            index=None,
            placeholder="Dienstverhältnis auswählen",
        )
		name = st.text_input("Name des/r neuen Mitarbeiters/in")
        safe_name = html.escape(name)  # HTML-Encoding
        persnr = st.text_input("Personalnummer des/r neuen Mitarbeiters/in")
        safe_persnr = html.escape(persnr)  # HTML-Encoding
        nutzerid = st.text_input("UserID des/r neuen Mitarbeiters/in")
        safe_nutzerid = html.escape(nutzerid)  # HTML-Encoding
        geschlecht = st.selectbox(
            "Geschlecht",
            ("Weiblich", "Männlich", "Divers"),
            index=None,
            placeholder="Bitte auswählen",
        )
        eintrittsdatum = st.date_input(
            "Eintrittsdatum des/r neuen Mitarbeiters/in",
            value=None,
            format="DD.MM.YYYY",
        )
    with c2:
        austrittsdatum = st.date_input(
            "Austrittsdatum des/r neuen Mitarbeiters/in (sofern zutreffend)",
            value=None,
            format="DD.MM.YYYY",
        )
		teamleiter = st.text_input("Zuständige/r Teamleiter/in")
        safe_teamleiter = html.escape(teamleiter)  # HTML-Encoding
        pate = st.text_input("Pate/Patin")
        safe_pate = html.escape(pate)  # HTML-Encoding
	with c3:
		computer = st.selectbox(
            "Wird ein Computer benötigt? (Falls noch nicht über BASF Onboarder bestellt)",
            ("Ja", "Nein"),
            index=None,
            placeholder="Bitte auswählen",
        )
        kommentar = st.text_area("Kommentar")
        safe_kommentar = html.escape(kommentar)  # HTML-Encoding
    submit_button = st.form_submit_button(label="Abschicken", type=("primary"))

if submit_button:
    if "button_pressed" not in st.session_state:
        st.session_state.button_pressed = True

        # Generate the email
        message = f"""<html><body>
                    <p>Hallo zusammen, <br /><br />
                    <b>Name des/der neuen Mitarbeiters/in:</b> {safe_name} <br />
                    <b>Personalnummer des/der neuen Mitarbeiters/in:</b> {safe_persnr} <br />
                    <b>UserID des/der neuen Mitarbeiters/in:</b> {safe_nutzerid} <br />
                    <b>Geschlecht des/der neuen Mitarbeiters/in:</b> {geschlecht} <br />
                    <b>Eintrittsdatum des/der neuen Mitarbeiters/in:</b> {eintrittsdatum} <br />
                    <b>Austrittsdatum des/der neuen Mitarbeiters/in:</b> {austrittsdatum} <br />
                    <b>Zuständige/r Teamleiter/in:</b> {safe_teamleiter} <br />
                    <b>Pate/in:</b> {safe_pate} <br />                    
                    <b>Wird ein Computer benötigt:</b> {computer} <br />
                    <b>Kommentar:</b> {safe_kommentar} <br /> <br />
                    <b>Viele Grüße {user_name}<b>
                    </p>
                </body>
            </html>
        """
        data = {
            "to": "max.Mustermann@test.de",
            "subject": "Neue/r Mitarbeiter/in",
            "text": message,
        }
        requests.post(
            "https://server/email/backend/mail?noreply=false",
            json=data,
            verify=False,
        )
        st.success("Die Email wurde erfolgreich versendet.")
    else:
        st.info("Die Email wurde bereits versendet.")

Thanks in advance for your help

I don’t see exactly where you’re using on_change, but my best guess is that the issue is from one of two possible issues:

  • The normal st.text_input doesn’t register any changes until you actually hit enter, or deselect the text input
  • st.form means that no input changes actually trigger anything

If it’s the first issue, one option is to use this component, which mimics st.text_input, but returns the new input every time you type any key GitHub - blackary/streamlit-keyup: Streamlit text input that returns value on keyup

If it’s the second issue, you could just not use st.form, and instead use a normal st.button to submit the results.

Hey,
Thanks for your input. Yes, in the postet code i do not use on_change because it did not work. This was only to show how i did it without on_change.
I will try your suggestions. Thanks a lot!

1 Like