onDragStop event in dashboard.Grid - streamlit_elements

Hello everyone,
I create dummy dashboard.Grid and try to realized next logic:
if dashboard.Item drag to column indexed 0 - it must return to previous location.

my code:

from streamlit_elements import elements, mui, html, dashboard
import streamlit as st
import json

    
st.write(st.session_state)

if 'layout_current' not in st.session_state:
        st.session_state['layout_current'] = [dashboard.Item("first_item", 1, 0, 1, 1)]
        st.session_state['rerun'] = False

with elements("dashboard"):
    def on_drag_stop_element(updated_layout):
        if not any(map(lambda x: x['x']==0, updated_layout)):
            st.session_state['layout_current'] = updated_layout
        else:
            st.session_state['rerun'] = True
     

    layout = st.session_state['layout_current']
    
    with dashboard.Grid(layout,
                        onLayoutChange=on_drag_stop_element,
                        style={"backgroundColor":"lightgrey"}):
                mui.Paper("First item", key="first_item")

if st.session_state['rerun']:
    st.session_state['rerun'] = False
    st.rerun()

Hi Nina,

I don’t know if this is what you are looking to accomplish, it is not clear in your post.

from streamlit_elements import elements, mui, dashboard
import streamlit as st
import json

# Inicializar el estado de la sesiĂłn si es la primera ejecuciĂłn
if 'layout_current' not in st.session_state:
    st.session_state['layout_current'] = [dashboard.Item("first_item", 1, 0, 1, 1)]
    st.session_state['previous_layout'] = []

# Función para manejar el cambio en el diseño
def on_layout_change(updated_layout):
    if any(item['x'] == 0 for item in updated_layout):  # Si hay algĂşn elemento en el Ă­ndice 0
        st.session_state['layout_current'] = st.session_state['previous_layout']  # Restaurar diseño anterior
    else:
        st.session_state['previous_layout'] = st.session_state['layout_current']  # Guardar diseño actual
        st.session_state['layout_current'] = updated_layout  # Actualizar diseño actual

    # Visualizar los Ă­ndices
    st.write("ĂŤndices actuales:")
    st.json(updated_layout)

# Obtener el diseño actual
layout = st.session_state['layout_current']

# Crear la interfaz de usuario con el elemento de dashboard
with elements("dashboard"):
    with dashboard.Grid(layout, onLayoutChange=on_layout_change, style={"backgroundColor": "lightgrey"}):
        mui.Paper("First item", key="first_item")

Thanks for the answer!
Yes, this is almost the logic that I need, but the problem is that if I move an element to the zero index twice in a row, the logic will not work the second time
The element must return to the range of valid values ​​every time (!= 0)
for example,
I expect the following behavior (steps for changing X-coordinate):
1 → 0 =1
1 → 2 = 2
2 → 0 = 2
2 → 0 = 2 (second time!)
2 → 0 = 2 (third and more time in a row)
2 → 3 = 3
3 → 0 = 3
3 → 1 = 1
etc…

The problem is that when you pass through index 0 for the second time your session state is zero. 2 → 0 = 2
2 → 0 = 0 (second time!)

Yes,
but if I (as a test) edit “on_layout_change” function this way (always return to fixed layout from 0)

# Función para manejar el cambio en el diseño
def on_layout_change(updated_layout):
    if any(item['x'] == 0 for item in updated_layout):  # Si hay algĂşn elemento en el Ă­ndice 0
        st.session_state['layout_current'] = [dashboard.Item("first_item", 1, 0, 1, 1)]#st.session_state['previous_layout']  # Restaurar diseño anterior
    else:
        st.session_state['previous_layout'] = st.session_state['layout_current']  # Guardar diseño actual
        st.session_state['layout_current'] = updated_layout  # Actualizar diseño actual

it still doesn’t work on the second or more trigger
Even though I don’t even set previous_layout :frowning:

See this modification if it is similar to what you are looking for

from streamlit_elements import elements, mui, dashboard
import streamlit as st

# Inicializar el estado de la sesiĂłn si es la primera ejecuciĂłn
if 'layout_current' not in st.session_state:
    st.session_state['layout_current'] = [dashboard.Item("first_item", 1, 0, 1, 1)]
    st.session_state['previous_layout'] = []

# Función para manejar el cambio en el diseño
def on_layout_change(updated_layout):
    # Obtener el diseño actual
    current_layout = st.session_state['layout_current']
    
    # Si hay algún elemento en el índice 0 en el diseño actual
    if any(item['x'] == 0 for item in updated_layout) and current_layout[-1]['x'] != 0:
        # Restaurar el diseño anterior
        st.session_state['layout_current'] = st.session_state['previous_layout']  
    else:
        # Guardar el diseño actual como diseño anterior
        st.session_state['previous_layout'] = current_layout
        # Actualizar el diseño actual
        st.session_state['layout_current'] = updated_layout  

    # Visualizar los Ă­ndices
    st.write("ĂŤndices actuales:")
    st.json(updated_layout)
# Obtener el diseño actual
layout = st.session_state['layout_current']

# Crear la interfaz de usuario con el elemento de dashboard
with elements("dashboard"):
    with dashboard.Grid(layout, onLayoutChange=on_layout_change, style={"backgroundColor": "lightgrey"}):
        mui.Paper("First item", key="first_item")

This still doesn’t work in the situation “1 → 0 = 1; 1->0 = 1” (card stay in 0 after second dragging)
I assume that the problem is in the “streamlit_elements.core.frame.elements_frame.dashboard” key, which appears in the session state after dragging cards, but I haven’t figured out how to use it yet

my code now:
I replaced “OnLayoutChange” method with method “onDragStop”
I almost achieved the desired behavior, the only problem left is “stay in 0 after second drag”

from streamlit_elements import elements, mui, html, dashboard
import streamlit as st

def on_drag_stop_element(layout):
    if not any(map(lambda x: x['x']==0, layout)):
        st.session_state['layout_current'] = layout
        # st.session_state['layout_current_new'] = layout
    if any(map(lambda x: x['x']==0, layout)):
        st.session_state['rerun'] = True
        
    
if 'layout_current' not in st.session_state:
        # print('init')
        layout = [dashboard.Item("first_item", 1, 0, 1, 1)]
        st.session_state['layout_current'] = layout
        st.session_state['layout_current_new'] = layout
        st.session_state['rerun'] = False
        
# st.write(st.session_state)

with elements("dashboard"):
    layout = st.session_state['layout_current_new']
        
    with dashboard.Grid(layout,
                        onDragStop=on_drag_stop_element,
                        style={"backgroundColor":"lightgrey"}):
        mui.Paper("First item", key="first_item")


if st.session_state['rerun'] == True:
    st.session_state['rerun'] = False
    st.session_state['layout_current_new'] = st.session_state['layout_current']
    st.rerun()

I greatly admire your persistence in this issue, and I will try to provide you with a solution :point_down:

from streamlit_elements import elements, mui, html, dashboard
import streamlit as st
import copy
import time
         
def on_drag_stop_element(layout, oldItem):  
    print(layout)
    st.session_state['layout_current'] = layout
    st.session_state['i'] = 1
    if any(map(lambda x: x['x']==0, layout)):
        st.session_state['i'] = 0
        st.session_state['i0'] = 0
        
    
if 'layout_current' not in st.session_state:
        layout = [dashboard.Item("first_item", 1, 2, 1, 1)]
        st.session_state['layout_current'] = layout
        st.session_state['i'] = 0 
        st.session_state['i0'] = 1 

with elements("dashboard"):  
    with dashboard.Grid(st.session_state['layout_current'],
                        onDragStop=on_drag_stop_element,
                        style={"backgroundColor":"lightgrey"}
                        ):
        mui.Paper("First item", key=f"first_item")

if st.session_state['i'] == 0:
    time.sleep(0.05)
    st.session_state['i'] = 2
    st.session_state['layout_current'][0]['x'] = st.session_state['i']
    st.rerun() 
2 Likes

Wow! Thank you!
this is absolutely what I need! You really helped me! :cupid:

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.