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.