Drag-and-drop with Datatable

The library supports drag-and-drop within a table or several tables on the page.

Moving rows

To enable the drag-and-drop support for rows, set the drag parameter to true.

Enabling the drag-and-drop support for rows

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

To drag/drop rows between several tables you should enable the drag parameter in each of them.

Related sample:  Drag-and-Drop between tables in DataTable

The 'order' mode

There is a special drag-and-drop mode - 'order'.

In such a mode, rows can't be dragged out of the table boundaries. Also, while dragging an item the remaining items are automatically rearranged so that when you drop the item to the final destination the remaining items won't need to do any rearrangements.

To enable the d-n-d support and activate the 'order' mode, just set the drag parameter to order.

Activating the 'order' mode for rows

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

Related sample:  The 'order' mode for rows

Moving columns

To enable the drag-and-drop support for columns, set the dragColumn parameter to true.

Enabling the drag-and-drop support for columns

webix.ui({
    view:"datatable",
    ...
    dragColumn:true
});

To drag/drop columns between several tables you should enable the dragColumn parameter in each of them.

Related sample:  Drag-and-Drop support for columns

There are three events that will be useful during column drag-n-drop process:

  • onBeforeColumnDrag - fires the moment you start dragging the column from its source position
  • onBeforeColumnDrop - fires the moment you drop the column to its target position
  • onAfterColumnDrop - fires after the column has been dragged and dropped to the target position

The 'order' mode

There is the 'order' mode for the table columns.

In that mode, columns can't be dragged out of the table boundaries. Also, while dragging a column the remaining columns are automatically rearranged so that when you drop the column to the final destination the remaining columns won't need to do any rearrangements.

To enable the d-n-d support and activate the 'order' mode for columns, just set the dragColumn parameter to order.

Activating the 'order' mode for columns

webix.ui({
    view:"datatable",
    ...
    dragColumn:'order'
});

Related sample:  The 'order' mode for columns

While dealing with column drag-n-drop in the "order" mode enabled the onBeforeColumnDrop and onAfterColumnDrop won't work. In this case you should make use of the events below:

Advanced

Information stated in the Common part is enough in most cases. The current part should be used just if you want to customize existing drag-and-drop behavior The part covers the following topics:

Custom text of the dragging items

To redefine the text displaying for the dragging item(s), you should use the onBeforeDrag event.
The desired template is set through the context.html property. You can use any HTML specifying the value for the property.

Displaying the number of the dragging items

dtable.attachEvent("onBeforeDrag", function(context, ev){
    context.html = context.source.length+" item(s)";
});

Some more use cases:

  • A fixed image and the id of the dragged row:

Displaying the dragged row id and some image

dtable.attachEvent("onBeforeDrag", function(context, ev){
    context.html = "<img src='some.gif'></img> " + context.start;
});
  • The text of the dragged items (in case of multiselect selection):

Displaying the title property of dragged items

dtable.attachEvent("onBeforeDrag", function(context, ev){
    context.html = "";
    for (var i=0; i< context.source.length; i++){
        context.html += context.from.getItem(context.source[i]).title + "<br>" ;
    }
});

Related sample:  Using events for customizing dnd

Denying dragging of specific items

To deny dragging of specific items you can use the onBeforeDrag event.

Denying dragging even items

dtable.attachEvent("onBeforeDrag", function(context, ev){
    if(dtable.getIndexById(context.start)%2==0){
        return false;      //denies dragging if the item index is even
    }
    return true;           //allows dragging in any other case
});

From now on, each time drag-n-drop is started, the item index will be checked, and the row can be dragged only if its index isn't even.

You can use the addCss method to mark items and hasCss to check whether an item has a certain marking.

Denying dropping to specific positions

To deny dropping to some positions, you can use the onBeforeDrop event and return false each time you want to block the operation.

Let's assume you specify a table on the page as below and want to deny dropping to the position of an item with 'id=2':

Denying dropping to a specific position

var dtable = new webix.ui({
    view:"datatable",
    ...
    data:[
        { id:1, title:"The Shawshank Redemption", year:1994},
        { id:2, title:"The Godfather",            year:1972},
        { id:3, title:"The Godfather: Part II",   year:1974}
    ]
});
dtable.data.addMark(2,"type", false,"b"); // adds a flag (type='b') to an item with id=2
 
dtable.attachEvent("onBeforeDrop", function(context, ev){
// if an item has flag type='b', denies dropping to the position of this item
        if(dtable.data.getMark(context.target,"type")=='b') return false;
        return true;
});

Switching between 'move' and 'copy' behavior

By default, rows are moved (not copied) while d-n-d.

To set the 'copy' behavior, use the onBeforeDrop event. Specify inside the copy logic and return false to prevent drag-and-drop processing:

Setting the 'copy' behavior for d-n-d

dtable.attachEvent("onBeforeDrop", function(context, ev){
    for (var i=0; i< context.source.length; i++){
        context.from.copy(context.source[i],context.start,this,webix.uid());
    }
    return false;
});

Related sample:  Using events for customizing dnd

Limiting the draggable area to the specified element

You can provide a behavior when the user could drag items only by the certain specified areas.

To achieve such a behavior, just follow this plan:

  • Specify an element you want an item to be dragged by.
  • Set this element as the target object for the onBeforeDrop event (the target object is an object on which the event will occur).
.webix_drag_handle{
    background-image:url(./handle.png);
    background-repeat: no-repeat;
}
 
var dtable = new webix.ui({
    view:"datatable",
    //...
    columns:[
        { id:"rank",    header:"", css:"rank" },
        { id:"title",   header:"Film title" },
        { id:"year",    header:"Released"},
        { id:"drag",    header:"", template:"<div class='webix_drag_handle'></div>" }   
    ],
    on:{
        onBeforeDrag:function(data, e){
                return (e.target||e.srcElement).className == "webix_drag_handle";
        }
    }
});

Related sample:  Limiting the draggable area for items (dragging rows)
Related sample:  Limiting the draggable area for items (dragging columns)

Scrolling during Drag And Drop

By default datatable will scroll self automatically when drag is near the top or bottom border. This behavior can be disabled by using dragScroll configuration property

webix.ui({
    view:"datatable",
    dragScroll:false
});

By default drag scroll works only for vertical scroll, you can enable it for both x and y directions by using

webix.ui({
    view:"datatable",
    dragScroll:"xy"
});

Related events

The following events are generated during the d-n-d process:

  • onBeforeDrag - fires before the mouse button is pressed and moved over a draggable item
  • onBeforeDragIn - fires before a dragged element is moved over the droppable area
  • onDragOut - fires when a dragged element is moved outside of the droppable area
  • onBeforeDrop - fires before a dragged element is released over the droppable area
  • onBeforeDropOut - fires before a dragged element is released over the droppable area (fires in the drag SOURCE component, not in the drag target one)
  • onAfterDrop - fires after drag-n-drop was finished

If the "order" mode is enabled, the onBeforeDrop and onAfterDrop events won't fire. In this case you need to use the corresponding events:

In the default scenario there is no need to use any of the mentioned events, because DataTable will process all the operations on its own. But sometimes default behavior needs customizing - this is the time when the mentioned events can be used.

Back to top