Better support for drag&drop #932
Replies: 8 comments 22 replies
-
I imagine an API like this: def handle_drop(e: events.SortableDropEventArguments) -> None:
ui.notify(f'Element {e.element} moved from {e.old_index} to {e.new_index}')
with ui.column().sortable(on_drop=handle_drop):
ui.label('A')
ui.label('B')
ui.label('C') By the way, we need to make sure it works in refreshable UIs: @ui.refreshable
def create_content(self) -> None:
with ui.column().sortable(on_drop=self.handle_drop):
for item in self.items:
ui.label(item.name) |
Beta Was this translation helpful? Give feedback.
-
There is also a Quasar/browser API limitation that prevents drag and drop from working on touch devices. https://quasar.dev/vue-directives/mutation#drag-and-drop-example However, I was able to recreate this example with touch support by using Vue.Draggable. |
Beta Was this translation helpful? Give feedback.
-
Do you think it's possible to change the cursor image by replacing the with self.props('draggable').classes('w-full cursor-pointer bg-grey-1'):
ui.label(item.title) |
Beta Was this translation helpful? Give feedback.
-
@sergeyyurkov1 hi, I know it's been late, but I did not know no touch support before I use drag-and-drop in my project. can you tell me how to modify drag-and-drop-example to support touch screen, I can not find anyone and any solution after search. |
Beta Was this translation helpful? Give feedback.
-
Custom draggable element from a template element from nicegui import ui
source = """
<template id='my-box'>
<style>
:host {
display: block;
padding: 10px;
color: white;
background-color: var(--color);
}
</style>
<slot></slot>
</template>
<script>
window.customElements.define('my-box', class extends HTMLElement {
constructor() {
super();
const templateEl = document.getElementById('my-box');
const templateContent = templateEl.content;
this.attachShadow({mode: 'open'}).appendChild(templateContent.cloneNode(true));
this.style.setProperty('--color', this.getAttribute('color') || 'gray');
}
});
</script>
"""
ui.add_body_html(source)
color = 'purple'
ui.html(f"<my-box color={color}>Hello, this is a message in a {color} box</my-box>")
ui.html(f"<my-box color={color} draggable='true'>You can drag me around!</div>")
ui.run() |
Beta Was this translation helpful? Give feedback.
-
from nicegui import globals, nicegui, ui
with ui.row().classes('sortable'):
for i in range(10):
with ui.card().classes('cursor-grab'):
ui.label(f'Item {i}')
@globals.sio.on('drop')
def drop(sid: str, msg: dict):
nicegui.get_client(sid).elements[msg['item_id']].move(target_index=msg['new_index'])
ui.add_body_html(r'''
<script type="module">
import 'https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.15.0/Sortable.min.js';
document.addEventListener('DOMContentLoaded', () => {
Sortable.create(document.querySelector('.sortable'), {
animation: 150,
ghostClass: 'opacity-50',
onEnd: (evt) => window.socket.emit("drop", {item_id: parseInt(evt.item.id), new_index: evt.newIndex }),
});
});
</script>
''')
ui.run() If ur are using ene change @Globals with nicegui |
Beta Was this translation helpful? Give feedback.
-
Any thoughts for making this work with refreshable? I have a sortable list that can be updated by other parts of the page but when element is refreshed it deletes and redraws it. The above methods only turn it into a sortable element on content load |
Beta Was this translation helpful? Give feedback.
-
In principle NiceGUI already supports drag&drop as demonstrated in the "Trello Cards" example. But there are limitations like controlling the cursor image while dragging an item.
I just tried SortableJS which is easy to integrate an comes with plenty of options. Maybe we can integrate it (or a similar library)? Here is a proof of concept:
Beta Was this translation helpful? Give feedback.
All reactions