Checking Streamlit inputs change to prevent manual input overwrite

PHOTO EMBED

Mon Jan 16 2023 02:42:55 GMT+0000 (Coordinated Universal Time)

Saved by @tofufu #python #streamlit

# ORRRRR save the inputs as "old" when submitting: ses["old_input"] = orig_input


import streamlit as st

st.set_page_config(page_title="PLAYGROUND", layout="wide")

# Init session states
if "num_changed" not in st.session_state:
    st.session_state["num_changed"] = False
if "select_changed" not in st.session_state:
    st.session_state["select_changed"] = False
if "old_res" not in st.session_state:
    st.session_state["old_res"] = 0
if "toggle_results" not in st.session_state:
    st.session_state["toggle_results"] = False

# on_change Changed fr selectbox, changed by selectbox is true so it can change the result input
def change_fr_select():
    st.write("Change fr select")
    st.session_state["select_changed"] = True
    st.session_state["num_changed"] = False

    st.session_state["toggle_results"] = False

    return

# on_change Changed fr num_input, changed by num_input is true to prevent result input from changing
def change_fr_num():
    st.write("Change fr num")
    st.session_state["num_changed"] = True
    st.session_state["select_changed"] = False

    st.session_state["toggle_results"] = True

    return

# Calc function
def calculate(num1, num2):
    st.write("num_changed", st.session_state["num_changed"])
    st.write("select_changed", st.session_state["select_changed"])
    st.write("toggle_results", st.session_state["toggle_results"])
    
    res = 0
    # selectbox has changed + we can calculate/overwrite input
    if st.session_state["select_changed"] == True:
        st.write("selectbox")
        res = num1 * num2
    # indep. num_input has changed + retain "old" answer result
    elif st.session_state["num_changed"]:
        st.write("num_input")
        res = st.session_state["old_res"]
    return res



# TODO checkbox to toggle between updated calculation or (manual) input

cols = st.columns((5, 5, 5, 5))

selection = cols[0].selectbox(label="Wheee", options=["one", "two", "three", "four"], on_change=change_fr_select)
assert selection is not None
list1 = {
    "one": 2,
    "two": 6,
    "three": 9,
    "four": 0
}
list2 = {
    "one": 1,
    "two": 8,
    "three": 4,
    "four": 3
}
num1 = cols[2].number_input(label="Num 1", value=list1[selection], on_change=change_fr_num)
num2 = cols[3].number_input(label="Num 2", value=list2[selection], on_change=change_fr_num)

together = calculate(num1, num2)
st.write(together)


result = cols[1].number_input(label="Result", value=together)
st.session_state["old_res"] = result
# TODO toggle b/w old and new results
if st.session_state["toggle_results"] == True:
    cols[1].checkbox("Different result detected!  Click to use new result", help="You changed one of the parameters used to estimate this value.  You can choose to use the estimation or keep your current value.")

st.write(st.session_state["select_changed"])
st.write(st.session_state["num_changed"])

st.markdown("---")






# Implementation
# num on_change Changed fr selectbox, changed by selectbox is true so it can change the num1 input
def change_fr_select(select_changed, num_changed, toggle_results):
    """ Change session state indicating that the selectbox has changed to determine if the num1 should be changed

        Arguments:
            select_changed {string} -- boolean session state indicating user changed selectbox value
            num_changed {string} -- boolean session state indicating user changed number_input value 
            toggle_results {string} -- boolean session state indicating we toggle option to switch between manual user input or recalculated modulus value
    """

    st.write("select")
    st.session_state[select_changed] = True     # user has changed selectbox value
    st.session_state[num_changed] = False       # thickness and density should not change modulus

    st.session_state[toggle_results] = False    # toggle whether recalculated modulus or manual input should not appear, selectbox should change the modulus 

    return



# select on_change
def select_on_change(select_changed, num_changed, old_result, toggle_results, index, case_n):
    st.write(select_changed, st.session_state[select_changed])
    st.write(num_changed, st.session_state[num_changed])
    st.write(toggle_results, st.session_state[toggle_results])

    res = 0
    # selectbox has changed + we can calculate/overwrite input
    if st.session_state[select_changed] == True:
        st.write("selectbox")
        st.session_state[old_result] = False
        res = 10**(31*st.session_state["num1_layer_" + str(index-1) + "_case_" + str(case_n)] - 1.89*((st.session_state["num2_layer_" + str(index-1) + "_case_" + str(case_n)]**29)))
    # indep. num_input has changed + retain "old" answer result
    elif st.session_state[num_changed] == True:
        st.write("num_input")
        st.session_state[old_result] = True

    return res


# num on_change Changed fr num_input, changed by number_input is true so it does NOT change the modulus input 
def change_fr_num(select_changed, num_changed, toggle_results):
    """ Change session state indicating that the bending stiffness thickness and/or density inputs have changed to determine if the modulus should be changed

        Arguments:
            select_changed {string} -- boolean session state indicating user changed selectbox value
            num_changed {string} -- boolean session state indicating user changed number_input value 
            toggle_results {string} -- boolean session state indicating we toggle option to switch between manual user input or recalculated modulus value
    """

    st.write("num")
    st.session_state[num_changed] = True        # num1 and num2 should change select
    st.session_state[select_changed] = False    # user has not changed selectbox value

    st.session_state[toggle_results] = True    # toggle whether recalculated modulus or manual input should appear, user can toggle between their own or recalculated value

    return
content_copyCOPY

Check Streamlit inputs, only overwrite num_input widgets if selecting different dropdown selection