Drag and drop functionality

I cannot find drag and drop functionality in Vaadin 10. There is the documentation for other releases, but I cannot find the classes in flow.

Hi,

that’s because the functionality doesn’t exist. It will hopefully be there in following releases, or as an add-on, but the feature was cut off from the Vaadin 10 release.

-Olli

Hi Frederik.

Drag and Drop is something that we do have in our backlog, but no timeline for it yet.

The Java API for basic HTML5 DnD features would not be that difficult to add, it would be quite similar to the one in Vaadin Framework 8.1. Having proper component support, like for Grid, is another thing that requires also support from the web component. I created an [issue]
(https://github.com/vaadin/flow/issues/3978) for the DnD Epic that you can go +1 and follow to get updates when we start working on the feature. It would be also very interesting to hear what are your specific use cases for DnD.

Before that, the HTML5 DnD can be used if necessary by enabling the DnD in polymer templates and handling the DnD events there, transmitting the necessary information to server side when needed.

Ok, thanks. I voted for the issue. My use case is a grid of images that needs to be re-ordered. Images can also be added dynamically to the end of the grid. I ended up using dragula, because the HTML5 API is too much work. Maybe this will help somebody else:

@DomEvent("dragula-drop")
class DnDDropEvent (source : DnDComponent,
                    fromClient : Boolean,
                    @EventData("event.detail.elementId") val exerciseId : String,
                    @EventData("event.detail.siblingId") val nextExerciseId : String) : ComponentEvent<DnDComponent>(source, fromClient) {

}


@JavaScript("frontend://bower_components/dragula/3.7.2/dist/dragula.min.js")
@StyleSheet("frontend://bower_components/dragula/3.7.2/dist/dragula.min.css")
open class DnDComponent() : Component() {

    init {
        UI.getCurrent().page.executeJavaScript("""
            var drake = dragula([$0]
);
            drake.on("drop", function(el, target, source, sibling) {
              $0.dispatchEvent(new CustomEvent("dragula-drop", {
                "detail": {
                    elementId: el.id,
                    siblingId: sibling.id
                 }
               }));
             });""", element)
    }

    fun appendChild(child : Element) {
        element.appendChild(child)
    }
}

// Dependency
compile("org.webjars.bower:dragula:3.7.2")

@StyleSheet("/static/exercise-reference-table.css")
@Tag(Tag.DIV)
class ExerciseReferenceTable  : DnDComponent(){

    val exercises : MutableList<Exercise> = mutableListOf()


    private val log = LoggerFactory.getLogger(ExerciseReferenceTable::class.java)

    fun findExercise(exerciseId : String) : Exercise  {
        val id = exerciseId.removePrefix("exercise-").toLong()
        return exercises.first { exercise -> exercise.id?.equals(id) ?: false }
    }

    init {
        element.setAttribute("class", "exercise-reference-table")
        addListener(DnDDropEvent::class.java, {e ->
            val exercise = findExercise(e.exerciseId)
            val nextExercise = findExercise(e.nextExerciseId)
            switch(exercise, nextExercise)
            log.info("Current order: " + exercises)
        })
    }

    fun switch(exercise : Exercise, nextExercise : Exercise) {
        exercises.remove(exercise)
        val indexOfNextExercise = exercises.indexOf(nextExercise)
        exercises.add(indexOfNextExercise, exercise)
    }


    fun appendExercise(exercise : Exercise) {

        val streamResource = StreamResource(
                "exerciseImage",
                InputStreamFactory {
                    ByteArrayInputStream(exercise.image)
                })
        val image = Image(streamResource, exercise.name)

        val exerciseCell = Div()
        exerciseCell.setClassName("exercise-reference-table__cell", true)
        exerciseCell.add(image)
        exerciseCell.setId("exercise-" + exercise.id)
        appendChild(exerciseCell.element)
        exercises.add(exercise)
    }

// Markup

.exercise-reference-table {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;

}

.exercise-reference-table__cell {
  padding: 1em;
  border: 1px solid black;
  display: flex;
  align-items: center;
}

}

Thanks for the sample, that will surely be helpful for others with a similar need :slight_smile:

Hi!

We really looking forward to this feature!

Our use case in Vaadin 8: we have layout and widgets (panels with own functionality) on it. The widgets can be dropped out (remove from the layout) or modify its order by drag and drop. We like to migrate our application from V8 to V10, but the lack of drag n drop prevents us to move on.

Thanks in advance!

Hi Károly,

did you take a look at this one already: https://vaadin.com/directory/component/html5-drag-and-drop-extension ?

-Olli

Thanks, I will try out.

Károly

The addon also now supports Polyfill and prevent iOS devices from scrolling around while dragging.

hi is the same extension for java instead of html

Check out the demo: https://github.com/stefanuebe/vaadin-html5-drag-and-drop/blob/master/demo/src/main/java/org/vaadin/stefan/dnd/demo/DragAndDropView.java