Drag-and-Drop in Webix UI

Not so long ago, the drag-and-drop functionality was used in web apps quite rarely. With HTML5 coming on the scene, native drag-and-drop has become easily accessible and popular. The functionality that required lots of coding efforts before, now can be added with a few lines of HTML code. While developing the Webix library, we tried to keep all features and advantages of native drag-and-drop. At the same time, we’ve added new capabilities that might be useful in web app development.

Component Level Drag-and-Drop

While HTML5 drag-and-drop is focused on an HTML element, Webix drag-and-drop concentrates on the UI components. For example, try to drag items between the tree and the grid in the demo below:

All Webix UI data-components support drag-and-drop functionality. With a single line of code, you can enable drag-and-drop for such components as List, DataTable, Tree, TreeTable, DataView.

webix.ui({
    view:"list",
    drag:true
});

If you have two components with enabled drag-and-drop on the page, it’s already enough to be able to drag elements between these components. There are no limitations for dragging rows from Grid into Tree or from TreeTable into List.

Such unrestricted drag-and-drop is hardly useful. That’s why Webix allows specifying roles of the components using the same drag property.

webix.ui({
    view:"tree",
    drag:"source"
});

webix.ui({
    view:"datatable",
    drag:"target"
});

Such initialization enables drag-and-drop only from Tree to DataTable (from the component marked as drag:”source” to the one marked as drag:”target” ).
The other drag-and-drop use case is reordering of items (rows, tree nodes, list items, etc). Webix provides a ready-to-use model for reordering, as well:

webix.ui({
    view:"list",
    drag:"order"
});

The component with enabled reordering mode allows drag-and-drop only within itself. For example, in case of grid, the user can reorder rows using drag-and-drop but can’t drag the rows outside the grid.

HTML Level Drag-and-Drop

Despite the fact that Webix is component oriented, Library supports drag-and-drop for custom HTML elements, as well. It provides an extra flexibility, as you utilize the Drag-and-Drop with your own HTML content or with some third party library.

Check the demo below and try to drag any grid’s row to the input:

To make any element on the page drop accessible, it’s enough to write something like:

   <input type="text" id="mytext">
    <script>
        webix.DragControl.addDrop("mytext");
    </script>

The above code snippet will allow the end user to drop any element from a Webix component into the HTML input. In real life app, we need to define which property of the dragged object will be shown in the input, so we need a bit more of code. Something similar to the following:

webix.DragControl.addDrop("mytext", {
    $drop:function(source, target, event){
        var dnd = webix.DragControl.getContext();
        target.value = dnd.from.getItem(dnd.source[0]).title;
    }
})

As you can see, it is the same code but we’ve also created a drop handler which defines data transformation logic.

The reverse task of dragging an HTML element into a Webix component is performed in a similar way:

<div id="divA" style='float:left; padding:20px; background-color:#dff;'> A </div>
<script>
    webix.DragControl.addDrag("divA");
</script>

To handle drag-and-drop correctly, we should specify onBeforeDrop event for the Webix component:

webix.ui({
    view:"datatable",
    on:{
        onBeforeDrop:function(context, e){
            this.getItem(context.target).title = context.source.innerHTML;
            this.refresh(context.target);
            return false;
        }
    }
});

Now try to drag any of the blocks into the datatable on the demo below. Row in the grid will be updated with content of the dragged box.

A
B
C

Native HTML5 Drag-and-Drop

While all the above samples are using custom drag-and-drop implementation, it’s possible to make a bridge between HTML5 and native drag-and-drop.
The following code is necessary to create a draggable HTML5 element:

<div draggable="true" ondragstart="drag(event)" > A </div>
<script type="text/javascript" charset="utf-8">
function drag(ev){
    ev.dataTransfer.setData("title",ev.target.innerHTML);
}
</script>

To set a Webix component as a drop target for such HTML container, you can use the code like this:

var mygrid = webix.ui{
    view:"datatable",
};

webix.event(mygrid.$view, "dragover", function(e){ e.preventDefault(); });
webix.event(mygrid.$view, "drop", function(e){
    var grid = $$(e);
    var id = grid.locate(e);
    grid.getItem(id).title = e.dataTransfer.getData("title");
    grid.refresh(id);
});

With this code, we are:

  • creating Webix datatable component
  • attaching dragover handler to enable HTML5 dropping in the grid’s area
  • attaching drop handler to define how the data of dragged element need to be used in the grid

As a result, a custom HTML element can be dragged and dropped into the Webix datatable. In a similar way, we can combine any existing drag-and-drop solution, based on HTML5, and Drag-and-Drop functionality of Webix.

Conclusion

As you can see, there are a lot of different ways to use drag-and-drop in Webix components, and all of them are easy to implement. The above samples show the basics of drag-and-drop implementations. However, this functionality contains far more events and configuration options. If needed, any drag-and-drop aspect is easily redefined. You can learn more about this from documentation.

Due to the Webix’s flexibility, you can stick with Webix drag-and-drop implementation, use native HTML5 drag-and-drop, or combine them both for ultimate user experience.