How to create two columns drag and drop app by using streamlit_dnd

Welcome to the Streamlit community! Thanks for sharing your code and error details—you’re definitely on the right track with streamlit-dnd for drag-and-drop between columns. The error you’re seeing, IndexError: pop index out of range, usually means the drag-and-drop event is trying to move an item from a list index that doesn’t exist, often due to a mismatch between the UI and the underlying data structure.

Here’s a step-by-step, minimal example for a two-column drag-and-drop layout using streamlit-dnd, based on the official streamlit-dnd demo:

import streamlit as st
from streamlit_dnd import dnd, apply_move

# Initialize items in session state
if "items" not in st.session_state:
    st.session_state.items = {
        "left": ["Task A", "Task B", "Task C", "Task D"],
        "right": ["Task 1A"]
    }

col1, col2 = st.columns(2)

# Render left column
with col1:
    with st.container(key="left", border=True):
        st.subheader("To Do")
        for it in st.session_state.items["left"]:
            with st.container(key=f"item_{it}", border=True):
                st.write(it)

# Render right column
with col2:
    with st.container(key="right", border=True):
        st.subheader("Done")
        for it in st.session_state.items["right"]:
            with st.container(key=f"item_{it}", border=True):
                st.write(it)

# Enable drag-and-drop after rendering containers
event = dnd("left", "right")

# Apply move and rerun if an event occurred
if event:
    apply_move(event, st.session_state.items)
    st.rerun()

Key points:

  • Use the same keys (“left”, “right”) for both the containers and the dnd function.
  • Always call dnd() after rendering the containers.
  • Only call apply_move() and st.rerun() if event is not None.
  • Make sure the lists in st.session_state.items are not being modified elsewhere during the same rerun.

If you still see the error, double-check that the items in your lists are unique and that the UI matches the state. If possible, share a minimum reproducible example or your full code/repo for more targeted help. Community members, feel free to jump in with your insights!

Sources: