Drag-and-Drop Support

The library supports drag-and-drop within a grid or several grids on the page.

Common

To enable the possibility to drag-and-drop rows in the grid, you should call method enableDragAndDrop() with the true parameter:

Enabling drag-and-drop in the grid

mygrid = new dhtmlXGridObject('gridbox');
...
mygrid.enableDragAndDrop(true);
mygrid.init();

The dragContext object

The dragContext object is available during the onDrag event and contains the following properties:

  • dragContext.source - type of the source component (“tree”,”grid”,”treeGrid”);
  • dragContext.target - type of the target component;
  • dragContext.sobj - the source object;
  • dragContext.tobj - the target object;
  • dragContext.dropmode - whether the dragged item will be a “child” or a “sibling”;
  • dragConetxt.mode - whether the dragged item will be copied or just moved: “copy” or “move”;
  • dragContext.sid - id of the dragged item;
  • dragContext.tid - id of the drag landing item.

Drag-and-drop related methods

  • enableDragAndDrop() - enables/disables drag-and-drop in the grid(s) on the page
mygrid.enableDragAndDrop(true);
  • enableDragOrder() - switches to the mode when the dragged items are dropped in the target location in the same order they were selected in the source location. Makes sense for multiple selection model only
mygrid.enableDragOrder(true);
  • enableMercyDrag() (PRO version) - enables the mode when items are dragged without removing (copying instead of moving)
mygrid.enableMercyDrag(true);
  • setDragBehavior() - sets the drag-and-drop behavior (see details in the API reference)
mygrid.setDragBehavior(sibling);
//the item is dropped as a sibling of the target item
  • enableColumnMove() (PRO version) - allows you to move columns with drag-and-drop
mygrid.enableColumnMove(true);
mygrid.attachEvent("onBeforeCMove",function(sInd,tInd){
    return confirm("Allows you to move column "+sInd+" to position "+tInd);
}); //return 'true' to allow moving, 'false' - to prohibit it

Related sample:  Drag and Drop between Grids

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 behaviour.

The part covers the following topics:

Custom text of the dragging items

To redefine the text displaying for the dragging item(s), use the rowToDragElement property. Inside the dragged text you can use any HTML.

mygrid.rowToDragElement=function(id){
    //any custom logic here
    return text;
}

Let's consider use-cases of specifying the following content:

  • A fixed image and the value of the dragged row in the first column:
mygrid.rowToDragElement=function(id){
    var text = "<img src='some.gif'> - " + mygrid.cellById(id,0).getValue();
    return text;
}
  • The number of dragged items (in case of multiselect selection):
mygrid.rowToDragElement=function(id){
    //_dragged.length - the number of dragging items
    var text = mygrid._dragged.length + "item(s)";
    return text;
}
  • The text of the dragged items (in case of multiselect selection):
mygrid.rowToDragElement=function(id){
    var text="";
    for (var i=0; i<this._dragged.length; i++)
        text += mygrid.cellById(mygrid._dragged[i].idd,0).getValue() + "<br/>";
    return text;
}

Denying dragging of specific items

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

Let's assume, you load data from an XML file and want to deny dragging of some rows. For this purpose, mark the unnecessary rows in any possible way, e.g. by user data:

<rows>
    <row id="1"><cell> data 1 </cell></row>
    <row id="2"><cell> data 2 </cell>
        <userdata name="drag">deny</userdata>
    </row>
</rows>

And then define the event handler as follows:

mygrid.attachEvent("onBeforeDrag",function(id){
    // denies dragging if user data exists
    if (grid.getUserData(id,"drag")=="deny") return false;
    // allows dragging in any other case
    return true;                                        
}

From now on, each time d-n-d starts, user data of the dragged item will be checked, and the row can be dragged only if it isn't marked as 'denied'.

Denying dropping to specific positions

To deny dropping to some positions (e.g. to allow dragging A to B, but deny dragging A to C), you can use the onDragIn or onDrag events and return false each time you want to block the operation.

Let's assume you load data from an XML file and want to deny dropping items A to positions of items B. For this purpose mark rows based on the mentioned rule in any possible way, e.g. by userdata:

<rows>
    <row id="1"> <cell> data 1 </cell> <userdata name="drag">A</userdata> </row>
    <row id="2"> <cell> data 2 </cell> <userdata name="drag">B</userdata> </row>
</rows>

And then define event handler as follows:

mygrid.attachEvent("onDragIn",function(sid,tid){
    // nothing can be dropped in a row marked as 'B'
    if (mygrid.getUserData(tid,"drag")=="B") return false; 
    // allows dropping in any other cases
    return true;                                   
});
//or
mygrid.attachEvent("onDrag",function(sid,tid){
    if (mygrid.getUserData(tid,"drag")=="B") return false;
    return true;
});

The described scenario make more sense for TreeGrid, but it can also be used with some customization in case of a plain Grid.

Switching between 'move' and 'copy' behaviors

By default, rows are moved (not copied) during the d-n-d operation.

To add some custom rules to this behavior use the moveRowTo() method.

mygrid.attachEvent("onDrag",function(sid,tid){
    // moves an item as a sibling of some other element
    mygrid.moveRowTo(sid,someID,"copy","sibling");
    // blocks default d-n-d
    return false;                                   
});

To enable the 'copy' behavior, set the enableMercyDrag command to true.

mygrid.enableMercyDrag(true);

You have one more way to set the 'copy' behavior - the dragContext object, available only for the onDrag event.

mygrid.attachEvent("onDrag",function(sid,tid){
    // copies an item instead of moving it
    if (!some_check(sid,tid)) mygrid.dragContext.mode="copy"; 
    return true;
});

In case of dhtmlxTreeGrid, you have the method setDragBehavior() to set the desired type of behavior:

mygrid.setDragBehavior("child"); // the item is dropped as a child of the target item

In order not to move or copy an item and apply just some custom logic to it, just return true within the onDrag event handler.

mygrid.attachEvent("onDrag",function(sid,tid){
    some_custom_code(sid,tid);
    return false;
});

Customizing the 'drag' action

The 'drag' action can be customized with the help of the onDragIn, onDragOut events.

Let's consider the following scenario: each time the dragged item enters the borders of any possible dropping its background is coloured in red. When the item is moved outside the dropping's borders - the background is cleared.

// sid - id of dragged item , tid - id of dropping item
mygrid.attachEvent("onDragIn",function(sid,tid,sgrid,tgrid){
    if (tid)    // tid may be null if dropping is in the grid body
        mygrid.setRowTextStyle(tid,"background-color:red;");// marks current dropping
    return true;                                                          
})
 
mygrid.attachEvent("onDragOut",function(tid){
    if (tid)
        mygrid.setRowTextStyle(tid,""); // clears styles set on the previous step
})

Dragging between several grids

To customize the 'drag' action between several grids, use the gridToGrid property.

//snippet just copies the data, without applying any modifications to it
mygrid.gridToGrid = function(rowId,sgrid,tgrid){
      var z=[]; 
      for (var i=0; i<sgrid.getColumnCount(); i++) //applies to each cell in source grid
          z[i]=sgrid.cellById(rowId,i).getValue(); // prepares data for the target grid
      return z;
}

In case when d-n-d occurs between dhtmlxTree and dhtmlxGrid, the same can be done by using the treeToGridElement and gridToTreeElement elements:

//from dhtmlxGrid to dhtmlxTree
mygrid.gridToTreeElement = function(tree,treeID,gridID){
    // takes data from 1st column as value for tree
    return this.cellById(gridId,0).getValue(); 
}
 
//from dhtmlxTree to dhtmlxGrid
mygrid.treeToGridElement = function(tree,treeID,gridID){
    // sets the tree text as a value of 1st column in the grid
    var z=[treeObj.getItemText(treeID)];    
    return z;
}

Related events

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

  • onBeforeDrag - fires when drag operation is started; the event can be blocked;
  • onDragIn - fires when an item is dragged to another potential target; the event can be blocked;
  • onDragOut - fires when an item is dragged out from the potential target;
  • onDrag - fires when an item is dragged to another target and the mouse is released; the event can be blocked;
  • onDrop - fires when an item is already placed in its final position. It can be used to catch the moment when the operation is finished.

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

Related sample:  Drag-and-drop events

Back to top