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.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
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