I have been using experimental fragments decorators with functions that included st.slider objects - this worked in version 1.35 (@st.experimental_fragment). However I have just upgraded to the latest version of streamlit 1.37 (where the decorator has changed to @st.fragment) and now the code creates an error:
Fragments cannot write to elements outside of their container.
Initially I did not understand the error but with some more digging it turns out that you can not add “slider like objects” to containers created outside of the fragment (in my work flow I define the page layer up front which creates theses issues - this wasn’t obvious to me when reading the docs!).
I made a little worked example where sliders do work within a @st.fragment decorator based one of the streamlit tutorials Create a fragment across multiple containers - Streamlit Docs. Thought this might be useful for anyone else who might be encountering a similar issues. The code works but oddly has an issues in rendering st.title within the fragements (no idea!).
import streamlit as st
import time
st.title("Cats!")
row1 = st.columns(3)
row2 = st.columns(3)
row3 = st.columns(2)
grids = [col.container(height=200) for col in row1 + row2]
grids1 = [col.container(height=400) for col in row3]
if 'slider_status' not in st.session_state:
st.session_state['slider_status'] = False
if 'first_run' not in st.session_state:
st.session_state['first_run'] = True
def black_cats(paw_count=4):
time.sleep(0.5)
st.title("🐈⬛ 🐈⬛")
st.markdown(" ".join(["🐾"]*paw_count))
# st.slider("Black Paws 1", 0, 10) # <- slider placed here creates an error
def orange_cats(paw_count=4):
time.sleep(0.5)
st.title("🐈 🐈")
st.markdown(" ".join(["🐾"]*paw_count))
@st.fragment
def herd_black_cats(card_a, card_b, card_c):
st.button("Herd the black cats")
paw_count = st.slider("Black Paws", 0, 10)
container_a = card_a.container()
container_b = card_b.container()
container_c = card_c.container()
with container_a:
black_cats(paw_count)
with container_b:
black_cats(paw_count)
with container_c:
black_cats(paw_count)
@st.fragment
def herd_orange_cats(card_a, card_b, card_c):
st.button("Herd the orange cats")
paw_count = st.slider("Orange Paws", 0, 10)
container_a = card_a.container()
container_b = card_b.container()
container_c = card_c.container()
with container_a:
orange_cats(paw_count)
with container_b:
orange_cats(paw_count)
with container_c:
orange_cats(paw_count)
@st.fragment
def herd_black_cats1():
st.button("Herd the black cat 1")
paw_count = st.slider("Black Paws 1", 0, 10)
black_cats(paw_count)
@st.fragment
def herd_orange_cats1():
r1 = st.empty()
r2 = st.empty()
r3 = st.empty()
with r2:
paw_count = st.slider("Orange Paws 1", 0, 10)
with r3:
st.button(f"Herd the orange cat 1 with {paw_count} paw prints")
with r1:
orange_cats(paw_count) # st.title does not render when called
with grids1[0].container():
herd_black_cats1()
with grids1[1].container():
herd_orange_cats1()
with st.sidebar:
herd_black_cats(grids[0],grids[2], grids[4])
herd_orange_cats(grids[1], grids[3], grids[5])
st.button("Herd all cats")