a suite of UI Components for development of web apps
Advanced User Interface Controls and Components
Created: 15 September 2015
By default during drag drop operations in AngularJS Grid, we can move rows within the same grid or to other components like TreeView or another grid. In some cases, instead of moving the source row, we may need to create a copy row and place it at some position in the same grid or move it to another grid. This article presents how to create a copy row and then move it using custom drag drop operation.
Similar: Grid Component for Angular 2
In order to create a copy row, we need to create a new row object and then set the corresponding object fields with data from original row. In our example, we only have few row fields, but this can be handled for any custom object fields:
angular
.module("appModule", ["integralui"])
.controller("appCtrl", ["$scope", "IntegralUITreeGridService", "$timeout", function($scope, $gridService, $timeout){
// The name of the first grid used as unique identifier
$scope.gridName = "gridSample";
// The name of the second grid used as unique identifier
$scope.gridName2 = "gridSample2";
// Columns for first grid
$scope.columns1 = [
{ headerText: "Header1", footerText: "Footer1", width: 150 },
{ headerText: "Header2", footerText: "Footer2", width: 120 },
{ headerText: "Header3", footerText: "Footer3" }
];
// Rows for first grid
$scope.rows1 = [
{ id: 1, text: "Item1", cells: [{ text: "Item11" }, { text: "Item12" }, { text: "Item13" }] },
{ id: 2, text: "Item2", cells: [{ text: "Item21" }, { text: "Item22" }, { text: "Item23" }] },
{ id: 3, text: "Item3", cells: [{ text: "Item31" }, { text: "Item32" }, { text: "Item33" }] },
{ id: 4, text: "Item4", cells: [{ text: "Item41" }, { text: "Item42" }, { text: "Item43" }] },
{ id: 5, text: "Item5", cells: [{ text: "Item51" }, { text: "Item52" }, { text: "Item53" }] },
{ id: 6, text: "Item6", cells: [{ text: "Item61" }, { text: "Item62" }, { text: "Item63" }] },
{ id: 7, text: "Item7", cells: [{ text: "Item71" }, { text: "Item72" }, { text: "Item73" }] }
];
// Columns for second grid
$scope.columns2 = [
{ headerText: "Header1", footerText: "Footer1", width: 150 },
{ headerText: "Header2", footerText: "Footer2", width: 200 },
{ headerText: "Header3", footerText: "Footer3" }
];
// Rows for second grid
$scope.rows2 = [];
// Create a copy cell from original cell
var createCopyCell = function(cell){
var copyCell = {
text: cell.text
}
return copyCell;
}
// Create a copy row from original row
var createCopyRow = function(row, parentId){
// Make sure the new row has a unique identifier
var copyRow = {
id: createId(),
text: row.text
}
// Create a copy cell for each cell in orginal row
if (row.cells && row.cells.length > 0)
for (var i = 0; i < row.cells.length; i++){
if (!copyRow.cells)
copyRow.cells = [];
copyRow.cells.push(createCopyCell(row.cells[i]));
}
return copyRow;
}
}]);
<div>
<iui-treegrid name="{{gridName}}" columns="columns1" rows="rows1" allow-drag="true" allow-drop="true" style="width:400px;margin-right:30px"></iui-treegrid>
<iui-treegrid name="{{gridName2}}" columns="columns2" rows="rows2" allow-drag="true" allow-drop="true" style="width:400px;"></iui-treegrid>
</div>
We need to make sure the identifier of the copy row is different from the one of original row. For this purpose, we will create a unique id using the following function:
// A function that creates a unique identifier
var createId = function(){
function shortString() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return (shortString() + shortString() + '-' + shortString()).substring(0, 4);
}
As a result, we have a new row that is exact copy of the original row.
Now we can place the copied row to some position either in original grid or to another grid. In our example, we are using custom drag drop, so that whenever a row is dragged, instead of moving a row, we will create and move the copy row.
Related: Drag Drop Multiple Rows in AngularJS Grid
To manage this during drag drop, we need to handle the dragDrop event and override the built-in functionality with our own custom operation. Whenever a row is dropped this event is fired, and here we can create a copy row and place it at target location within the target grid.
// Override the default drag drop by handlign the dragDrop event
$scope.onDragDrop = function(e){
if (e.dragRow){
// Create a copy row from dragged row
var copyRow = createCopyRow(e.dragRow);
// Insert the copied row at drop position
if (copyRow){
switch (e.dropPos){
case 1:
$gridService.insertRowBefore(e.targetTree, copyRow, e.targetRow);
break;
case 2:
$gridService.insertRowAfter(e.targetTree, copyRow, e.targetRow);
break;
default:
$gridService.addRow(e.targetTree, copyRow);
break;
}
}
// Make sure copied row is visible in current view of the grid
$gridService.ensureVisible(e.targetTree, copyRow);
// Mark the copied row as selected
var selTimer = $timeout(function(){
$gridService.selectedRow(e.targetTree, copyRow);
$timeout.cancel(selTimer);
}, 100);
// Return a false value so that the built-in drag drop will be overriden with above functionality
return false;
}
}
<div>
<iui-treegrid name="{{gridName}}" columns="columns1" rows="rows1" allow-drag="true" allow-drop="true" style="width:400px;margin-right:30px" drag-drop="onDragDrop(e)"></iui-treegrid>
<iui-treegrid name="{{gridName2}}" columns="columns2" rows="rows2" allow-drag="true" allow-drop="true" style="width:400px;" drag-drop="onDragDrop(e)"></iui-treegrid>
<br style="clear:both;"/>
</div>
We are also making sure that whenever row is placed, it is shown in grid current view and marked as selected.
As above demonstration shows, by dragging a row over left or right grid a drop marker will appear stating whether drag drop is allowed and where the copy row will be placed. You can do this within the same grid or move a copy row from left grid to the right grid and vice versa.