St.multiselect _after select function exit

Dear all.

I’m trying to make an python code with streamlit GUI, which is actually Linear programing calculator.

Currently I have a problem with funcstion novo ( ) inside my code.

import streamlit as st
import pandas as pd

# Load some example data.
data1 = st.cache(pd.read_excel)("ISHRANA_PERADI.xlsx", nrows=68, sheet_name='KRMIVA')
data2 = st.cache(pd.read_excel)("ISHRANA_PERADI.xlsx", nrows=40, sheet_name='POTREBE_PERADI')

st.write('Odaberite ishrambeni program.', data2)
selected_indices = st.multiselect('Odaberite ishrambeni program prateci indexe redova :', data2.index, key='sel_ind1')
selected_rows = data2.loc[selected_indices]
st.write('### Odabrani ishrambeni program je :', selected_rows)
row_index = selected_indices
col_index = st.selectbox("Odaberite ogranicenje O za formiranje jednacine Ogranicenja :", data2.columns, key='col_ind1')

def novo():
    st.write('Odaberite ishrambeni program.', data2)
    selected_indicesB = st.multiselect('Odaberite ishrambeni program prateci indexe redova :', data2.index,
                                      key='sel_indb')
    selected_rowsB = data2.loc[selected_indicesB]
    st.write('### Odabrani ishrambeni program je :', selected_rowsB)
    row_indexB = selected_indicesB
    col_indexB = st.selectbox("Odaberite ogranicenje O za formiranje jednacine Ogranicenja :", data2.columns,
                             key='col_indb')
    # Odaberite redove odnosno Krmiva po zelji. Na osnovu odabranih redova kreiraju se variable
    st.write('Odaberite željena Krmiva i ukupan broj istih.', data1)
    selected_indicesC = st.multiselect('Odaberite redove, odnosno željena Krmiva prateći indexe redova po Krmivima:', data1.index, key='sel_indc')
    selected_rowsC = data1.loc[selected_indicesC]
    st.write('### Odabrani redovi, odnosno Krmiva su:', selected_rowsC)

    new_dataC = pd.DataFrame(selected_rowsC)

    filteredC = st.multiselect("Odaberite parametre Ograničenja za Krmiva:", options=list(new_dataC.columns),
                              default=list(new_dataC.columns), key='filtC')

    st.write(new_dataC[filteredC])
    new_dataD = pd.DataFrame(filteredC)

    model = pulp.LpProblem('test', LpMinimize)

    ogra1 = ""
    relation = st.selectbox("Odaberite jednu od opcija: ", options=["=", "<=", ">="], key='relac2')

    if relation == "<=":

        if 'ME' in filtered:
            for rownum, row in new_data.iterrows():
                print(row)

                for i, schedule in enumerate(decision_variables):
                    print(schedule)

                    if len(str(schedule)) == 2:
                        print(str(schedule)[1])
                        a = str(schedule)[1]
                        broj = int(a)

                    if len(str(schedule)) > 2:
                        print(str(schedule)[1])
                        print(str(schedule)[2])
                        a = str(schedule)[1]
                        b = str(schedule)[2]
                        broj = int(a + b)

                    if rownum == broj:
                        print("ispunjen")
                        cell_value = data2.loc[row_indexB, col_indexB]
                        print(f"The value at row {row_indexB} and column {col_indexB} is {cell_value}")
                        st.write(cell_value)

                        formula = row['ME'] * schedule
                        ogra1 += lpSum([formula])
                        print(ogra1)
                        model += ogra1 <= cell_value

            print("Funkcija Ogranicenja: " + str(ogra1))
            st.write("Jednačina Ograničenja je: ", str(ogra1))

        elif 'SM' in filtered:
            for rownum, row in new_data.iterrows():
                print(row)

                for i, schedule in enumerate(decision_variables):
                    print(schedule)

                    if len(str(schedule)) == 2:
                        print(str(schedule)[1])
                        a = str(schedule)[1]
                        broj = int(a)

                    if len(str(schedule)) > 2:
                        print(str(schedule)[1])
                        print(str(schedule)[2])
                        a = str(schedule)[1]
                        b = str(schedule)[2]
                        broj = int(a + b)

                    if rownum == broj:
                        print("ispunjen")
                        cell_value = data2.loc[row_indexB, col_indexB]
                        print(f"The value at row {row_indexB} and column {col_indexB} is {cell_value}")
                        st.write(cell_value)

                        formula = row['SM'] * schedule
                        ogra1 += lpSum([formula])
                        print(ogra1)
                        model += ogra1 <= cell_value

            print("Funkcija Ogranicenja: " + str(ogra1))
            st.write("Funkcija Ogranicenja: " + str(ogra1))
button = st._main.button("Dodaj novo O:")

if button:
    novo()

If applicable, please provide the steps we should take to reproduce the error or specified behavior.

Expected behavior:
In normal, I expect that after I push button, def novo ( ) loads, and after I can normaly select and options from selected_indicesB, col_indexB, filteredC and finally ogra1 constraints is generated.

Actual behavior:

But, the problem is, when after I push button, def novo ( ) loads, and after I try to select any options from selected_indicesB novo( ) function exits imidiatelly.

Additional information

Here is a gif to see what is happening : WEB_2023-04-07_10_54.mp4 - Google Drive

This is an issue with nested buttons. A button returns True only for the page load resulting from its click, then goes back to False. Hence, if you interact with anything nested inside your button("Dodaj novo O:"), that content will immediately go away.

Check out this blog post for some workarounds:

1 Like

Dear mathcatsand.

I’ve read what you wrote and I made some progresion. Now, after I clicked on button, function novo () runs and I can choose from it some of options (st.multiselect widgets nad so on…). Here is updated code:


import streamlit as st
import pandas as pd

# Load some example data.
data1 = st.cache(pd.read_excel)("ISHRANA_PERADI.xlsx", nrows=68, sheet_name='KRMIVA')
data2 = st.cache(pd.read_excel)("ISHRANA_PERADI.xlsx", nrows=40, sheet_name='POTREBE_PERADI')

st.write('Odaberite ishrambeni program.', data2)
selected_indices = st.multiselect('Odaberite ishrambeni program prateci indexe redova :', data2.index, key='sel_ind1')
selected_rows = data2.loc[selected_indices]
st.write('### Odabrani ishrambeni program je :', selected_rows)
row_index = selected_indices
col_index = st.selectbox("Odaberite ogranicenje O za formiranje jednacine Ogranicenja :", data2.columns, key='col_ind1')

def novo():
    st.write('Odaberite ishrambeni program.', data2)
    selected_indicesB = st.multiselect('Odaberite ishrambeni program prateci indexe redova :', data2.index,
                                      key='sel_indb')
    selected_rowsB = data2.loc[selected_indicesB]
    st.write('### Odabrani ishrambeni program je :', selected_rowsB)
    row_indexB = selected_indicesB
    col_indexB = st.selectbox("Odaberite ogranicenje O za formiranje jednacine Ogranicenja :", data2.columns,
                             key='col_indb')
    # Odaberite redove odnosno Krmiva po zelji. Na osnovu odabranih redova kreiraju se variable
    st.write('Odaberite željena Krmiva i ukupan broj istih.', data1)
    selected_indicesC = st.multiselect('Odaberite redove, odnosno željena Krmiva prateći indexe redova po Krmivima:', data1.index, key='sel_indc')
    selected_rowsC = data1.loc[selected_indicesC]
    st.write('### Odabrani redovi, odnosno Krmiva su:', selected_rowsC)

    new_dataC = pd.DataFrame(selected_rowsC)

    filteredC = st.multiselect("Odaberite parametre Ograničenja za Krmiva:", options=list(new_dataC.columns),
                              default=list(new_dataC.columns), key='filtC')

    st.write(new_dataC[filteredC])
    new_dataD = pd.DataFrame(filteredC)

    model = pulp.LpProblem('test', LpMinimize)

    ogra1 = ""
    relation = st.selectbox("Odaberite jednu od opcija: ", options=["=", "<=", ">="], key='relac2')

    if relation == "<=":

        if 'ME' in filtered:
            for rownum, row in new_data.iterrows():
                print(row)

                for i, schedule in enumerate(decision_variables):
                    print(schedule)

                    if len(str(schedule)) == 2:
                        print(str(schedule)[1])
                        a = str(schedule)[1]
                        broj = int(a)

                    if len(str(schedule)) > 2:
                        print(str(schedule)[1])
                        print(str(schedule)[2])
                        a = str(schedule)[1]
                        b = str(schedule)[2]
                        broj = int(a + b)

                    if rownum == broj:
                        print("ispunjen")
                        cell_value = data2.loc[row_indexB, col_indexB]
                        print(f"The value at row {row_indexB} and column {col_indexB} is {cell_value}")
                        st.write(cell_value)

                        formula = row['ME'] * schedule
                        ogra1 += lpSum([formula])
                        print(ogra1)
                        model += ogra1 <= cell_value

            print("Funkcija Ogranicenja: " + str(ogra1))
            st.write("Jednačina Ograničenja je: ", str(ogra1))

        elif 'SM' in filtered:
            for rownum, row in new_data.iterrows():
                print(row)

                for i, schedule in enumerate(decision_variables):
                    print(schedule)

                    if len(str(schedule)) == 2:
                        print(str(schedule)[1])
                        a = str(schedule)[1]
                        broj = int(a)

                    if len(str(schedule)) > 2:
                        print(str(schedule)[1])
                        print(str(schedule)[2])
                        a = str(schedule)[1]
                        b = str(schedule)[2]
                        broj = int(a + b)

                    if rownum == broj:
                        print("ispunjen")
                        cell_value = data2.loc[row_indexB, col_indexB]
                        print(f"The value at row {row_indexB} and column {col_indexB} is {cell_value}")
                        st.write(cell_value)

                        formula = row['SM'] * schedule
                        ogra1 += lpSum([formula])
                        print(ogra1)
                        model += ogra1 <= cell_value

            print("Funkcija Ogranicenja: " + str(ogra1))
            st.write("Funkcija Ogranicenja: " + str(ogra1))

if "button3" not in st.session_state:
    st.session_state["button3"] = False

with st.sidebar:

    if st.button("Button3"):
        # toggle button3 session state
        st.session_state["button3"] = not st.session_state.get("button3", False)


if st.session_state.get("button3", False):
    novo()

But , this works only if I click on “button3” one time .If I click one more time then function novo() close imidiately. How can I update my code to enable user to use button3 what ever times they wont?
here is a gif of a problem:
WEB_2023-04-10_11_06

if "button3_clicked" not in st.session_state:
    st.session_state["button3_clicked"] = False

with st.sidebar:

    if st.button("Button3"):
        # Save that button3 has been clicked
        st.session_state["button3_clicked"] = True

if st.session_state['button3_clicked']:
    novo()

Your code created a toggle, so successive clicks would “turn on” and “turn off” your novo function. If you don’t want that, then you should only have information change one way (to True) instead of back and forth (not/opposite current state). I renamed the key in session state to highlight that a bit.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.