Streamlit - selectbox로 선택한 값 유지시키기
- 목차
해결 방법
`on_change` 파라미터에 session state에 선택한 값의 인덱스를 저장하는 함수를 넣고, 여기서 저장한 인덱스를 디폴트값으로 사용한다.
import streamlit as st
if "select_list" not in st.session_state:
st.session_state.select_list = ["S 1", "S 2", "S 3"]
if "option_list" not in st.session_state:
st.session_state.option_list = ["Option 1", "Option 2"]
if "selected" not in st.session_state:
st.session_state.selected = 0
page_option = st.radio(
"선택",
st.session_state.option_list,
index=0,
key="page_option"
)
def update():
st.session_state.selected = st.session_state.select_list.index(st.session_state.selected_option)
if page_option == "Option 1":
selected_option = st.selectbox(
"선택지",
st.session_state.select_list,
index=st.session_state.selected,
key="selected_option",
on_change=update
)
elif page_option == "Option 2":
options = st.multiselect(
'선택지들',
['S 1', 'S 2', 'S 3'],
key='options',
)
st.write(f"선택된 값들: {options}")
문제 상황
라디오버튼을 통해 선택한 것에 따라 페이지를 다르게 꾸미고 싶은 경우가 있다. 예를 들어, 아래처럼 Option 1을 선택하면 selectbox가 나오고, Option 2를 선택하면 multiselect가 나온다.
import streamlit as st
if "select_list" not in st.session_state:
st.session_state.select_list = ["S 1", "S 2", "S 3"]
if "option_list" not in st.session_state:
st.session_state.option_list = ["Option 1", "Option 2"]
page_option = st.radio(
"선택",
st.session_state.option_list,
index=0,
key="page_option"
)
if page_option == "Option 1":
selected_option = st.selectbox(
"선택지",
st.session_state.select_list,
key="selected_option",
)
st.write(f"선택된 값: {selected_option}")
elif page_option == "Option 2":
options = st.multiselect(
'선택지들',
['S 1', 'S 2', 'S 3'],
key='options',
)
st.write(f"선택된 값들: {options}")
이러면 Option 1에서 S 2를 선택했더라도 Option 2로 바꿨다가 다시 Option 1로 오면 선택했던 게 초기화되어 S 1이 선택되어있다. 나는 Option이 바뀌더라도 선택한 값은 계속 유지되었으면 했다.
해결 과정
해결 과정이라고 했지만 나의 실패 사례 모음이다.
1. 첫 번째 실패: session state에 index 업데이트 하기
if "selected" not in st.session_state:
st.session_state.selected = 0
if page_option == "Option 1":
selected_option = st.selectbox(
"선택지",
st.session_state.select_list,
key="selected_option",
index=st.session_state.selected
)
st.write(f"선택된 값: {selected_option}")
st.session_state.selected = st.session_state.select_list.index(selected_option)
나의 생각
(1) `st.selectbox`에서 `index` 인자를 지정하면 기본값으로 해당하는 값을 보여준다.
(2) 그러면 index 값을 session state에 넣어놓고 `index` 인자에 집어넣으면 되지 않을까?
결과
이렇게 하면 Option 2 갔다가 1로 돌아와도 선택했던 게 살아있다!
하지만 selectbox에서 선택지를 바꾸면 다시 원래 값으로 되돌아간다. (다시 선택하면 바뀌긴 한다)
이유? 모르겠다. 진짜로.
2. 두 번째 실패: key로 인덱스 지정하기
if "selected" not in st.session_state:
st.session_state.selected = "S 1"
if page_option == "Option 1":
selected_option = st.selectbox(
"선택지",
st.session_state.select_list,
key="selected",
index=st.session_state.select_list.index(st.session_state.selected)
)
st.write(f"선택된 값: {selected_option}")
나의 생각
(1) `selectbox`의 `key` 인자를 주면 선택한 값이 자동으로 session state에 저장된다.
(2) 그러면 그 값을 다음 `index` 인자로 찾아서 넣어주면 되지 않을까?
결과
Option 2로 갔다 오면 초기화 되어있다.
이유
추측컨대, `if`문 안에 `selectbox`가 있기 때문에, Option 2를 선택하면 `selectbox`의 존재 자체가 지워지면서 session state의 메모리도 지워지는 게 아닌가 싶다. 근데 이상한건 Option 2를 선택했을 땐 잘 살아있다가 다시 Option 1을 선택하면 사라진다는 점...