import streamlit as st # Streamlit widgets with persistence def is_filled(key_list): state_filled_key = "_".join(key_list) + "_filled" def on_change_action(): st.session_state.save_state[state_filled_key] = True return on_change_action def update_card_dict(key_list, use_default=None): state_key = "_".join(key_list) if st.session_state.save_state.get(state_key + "_filled", False) or use_default: card_key = key_list[-1] current_dict = st.session_state.card_dict for key in key_list[:-1]: current_dict = current_dict[key] current_dict[card_key] = st.session_state.save_state.get(state_key, use_default) def make_multiselect( key_list, label, options, format_func=lambda x: x, help="", default=None ): key = "_".join(key_list) if key in st.session_state: st.session_state.save_state[key] = st.session_state[key] elif default is not None: st.session_state.save_state[key] = default res = st.multiselect( label=label, options=options, format_func=format_func, key=key, default=st.session_state.save_state.get(key, []), on_change=is_filled(key_list), help=help, ) update_card_dict(key_list) return res def make_selectbox( key_list, label, options, format_func=lambda x: x, help="", index=None ): key = "_".join(key_list) if key in st.session_state: st.session_state.save_state[key] = st.session_state[key] elif index is not None: st.session_state.save_state[key] = options[index] res = st.selectbox( label=label, options=options, format_func=format_func, key=key, index=options.index( st.session_state.save_state.get(key, options[0]) ), # if st.session_state.save_state.get(key, options[0]) in options else 0, on_change=is_filled(key_list), help=help, ) update_card_dict( key_list, use_default=st.session_state.save_state.get(key, options[0]) ) # use the default value even without interactions return res def make_radio(key_list, label, options, format_func=lambda x: x, help="", index=None): key = "_".join(key_list) if key in st.session_state: st.session_state.save_state[key] = st.session_state[key] elif index is not None: st.session_state.save_state[key] = options[index] res = st.radio( label=label, options=options, format_func=format_func, key=key, index=options.index(st.session_state.save_state.get(key, options[0])), on_change=is_filled(key_list), help=help, ) update_card_dict( key_list, use_default=st.session_state.save_state.get(key, options[0]) ) # use the default value even without interactions return res def make_text_input(key_list, label, help="", value=None): key = "_".join(key_list) if key in st.session_state: st.session_state.save_state[key] = st.session_state[key] elif value is not None: st.session_state.save_state[key] = value res = st.text_input( label=label, key=key, value=st.session_state.save_state.get(key, ""), on_change=is_filled(key_list), help=help, ) update_card_dict(key_list) return res def make_text_area(key_list, label, help="", value=None): key = "_".join(key_list) if key in st.session_state: st.session_state.save_state[key] = st.session_state[key] elif value is not None: st.session_state.save_state[key] = value res = st.text_area( label=label, key=key, value=st.session_state.save_state.get(key, ""), on_change=is_filled(key_list), help=help, ) update_card_dict(key_list) return res def make_checkbox(key_list, label, help="", value=None): key = "_".join(key_list) if key in st.session_state: st.session_state.save_state[key] = st.session_state[key] elif value is not None: st.session_state.save_state[key] = value res = st.checkbox( label=label, key=key, value=st.session_state.save_state.get(key, False), on_change=is_filled(key_list), help=help, ) update_card_dict(key_list) return res