LIDOR SYSTEMS

Advanced User Interface Controls and Components

Drag Drop Multiple Rows in Angular Grid

Created: 19 October 2017

When multi selection is allowed, you can select multiple rows and drag drop them from one position to another within the same Grid or to other Grid components. This is handled automatically, but you can also further extend this functionality by handling events in your code.

Grid component is part of IntegralUI Web
a suite of UI Components for development of web apps

If you have any questions, don't hesitate to contact us at support@lidorsystems.com

In above demo, you can select multiple rows by holding CTRL or SHIFT key and clicking on rows in the Grid or by clicking on check boxes in first column. To start a drag drop operation, hold the left mouse button and drag the mouse cursor a little bit. If multiple rows are selected, they are all carried during drag drop, although the visual representation only shows the last selected row.

To create a copy of selected rows during drag drop, press and hold the SHIFT key and release the mouse button. Instead of original rows, a copy is created and dropped at target position. This allows you to choose whether you want to move or copy multiple rows during drag drop.

In similar way, you can drag drop multiple rows from one Grid to another, or to other Angular components.

How to Drag and Drop Multiple Rows

By default, dragging of rows is disabled. To enable it, set the allowDrag property to true. This allows you to start a drag drop operation on general level in the Grid component. In similar way, to allow rows to be dropped, set the allowDrop property true.

Now, you can drag and drop rows in the Grid. However, only one row can be dragged and dropped. To allow drag drop of multiple rows, you need to set multi selection active. For this purpose, set the selectionMode property to either MultiSimple or MultiExtended.

import { IntegralUISelectionMode } from './integralui/components/integralui.core';
. . .

public selMode: IntegralUISelectionMode = IntegralUISelectionMode.MultiExtended;
                            
<iui-grid [allowDrag]="true" [allowDrop]="true" [selectionMode]="selMode" (dragOver)="onGridDragOver($event)" (dragDrop)="onGridDragDrop($event)" [appRef]="applicationRef" [controlStyle]="gridStyle" [columns]="columns" [rows]="rows" [showFooter]="false" [gridLines]="gridLines" [allowDrag]="true" [allowDrop]="true" [selectionMode]="selMode" (afterSelect)="onGridAfterSelect($event)" (dragOver)="onGridDragOver($event)" #grid>
    <ng-template let-column [iuiTemplate]="{ type: 'header' }">
        {{column.headerText}}
    </ng-template>
    <ng-template let-cell [iuiTemplate]="{ type: 'cell' }">
        <span [ngSwitch]="cell.cid">
            <span *ngSwitchCase="1">
                <span class="grid-ddmr-cell-checkbox" [ngStyle]="{ 'background-image': getCheckValue(cell) }" (mousedown)="checkBoxClicked($event, cell)" (mouseup)="checkBoxMouseUp($event)"></span>
            </span>
            <span *ngSwitchDefault>
                <span class="grid-ddmr-cell-label">{{cell.text}}</span>
            </span>
        </span>
    </ng-template>
</iui-grid>
                            

Differences in Drag Over Event during Single and Multi Drag Drop

The difference between single and multi drag drop operation is in the value of dragRow field of the event data. When multiple rows are dragged, this field holds a reference to an array of all rows that are dragged, instead of just the last selected one. Consider this when handling the dragOver or dragDrop events in your code. For example:

onGridDragOver(e: any){
    if (Array.isArray(e.dragRow)){
        let list: Array = e.dragRow;

        // Proceed with action regarding drop of multiple rows
    }
    else {
        // Proceed with action regarding drop of a single row
    }
}
                            
<iui-grid [allowDrag]="true" [allowDrop]="true" [selectionMode]="selMode" (dragOver)="onGridDragOver($event)" (dragDrop)="onGridDragDrop($event)" [appRef]="applicationRef" [controlStyle]="gridStyle" [columns]="columns" [rows]="rows" [showFooter]="false" [gridLines]="gridLines" [allowDrag]="true" [allowDrop]="true" [selectionMode]="selMode" (afterSelect)="onGridAfterSelect($event)" (dragOver)="onGridDragOver($event)" #grid>
    <ng-template let-column [iuiTemplate]="{ type: 'header' }">
        {{column.headerText}}
    </ng-template>
    <ng-template let-cell [iuiTemplate]="{ type: 'cell' }">
        <span [ngSwitch]="cell.cid">
            <span *ngSwitchCase="1">
                <span class="grid-ddmr-cell-checkbox" [ngStyle]="{ 'background-image': getCheckValue(cell) }" (mousedown)="checkBoxClicked($event, cell)" (mouseup)="checkBoxMouseUp($event)"></span>
            </span>
            <span *ngSwitchDefault>
                <span class="grid-ddmr-cell-label">{{cell.text}}</span>
            </span>
        </span>
    </ng-template>
</iui-grid>
                            

In above code, a check to the e.dragRow field is set to determine whether the value is an array or a single object. Depending on this value, you can proceed with the event by adding custom action.

By default, the selection status is cleared and set only to the last selected row. Therefore, you need to set all checked rows as selected after they are dropped.

getCheckedList(): Array {
    let checkedList: Array = [];

    // Get a list of all checked rows
    let list =  this.grid.getList();
    for (let i = 0; i < list.length; i++){
        if (list[i].cells[0].value)
            checkedList.push(list[i]);
    }

    return checkedList;
}

onGridDragDrop(e: any){
    let self = this;

    // By default, internally the selection status is cleared
    // So you need to set all checked rows as selected after they are dropped
    setTimeout(function(){
        let list = self.getCheckedList();
        self.grid.selectRows(list);
    }, 1);
}
                            
<iui-grid [allowDrag]="true" [allowDrop]="true" [selectionMode]="selMode" (dragOver)="onGridDragOver($event)" (dragDrop)="onGridDragDrop($event)" [appRef]="applicationRef" [controlStyle]="gridStyle" [columns]="columns" [rows]="rows" [showFooter]="false" [gridLines]="gridLines" [allowDrag]="true" [allowDrop]="true" [selectionMode]="selMode" (afterSelect)="onGridAfterSelect($event)" (dragOver)="onGridDragOver($event)" #grid>
    <ng-template let-column [iuiTemplate]="{ type: 'header' }">
        {{column.headerText}}
    </ng-template>
    <ng-template let-cell [iuiTemplate]="{ type: 'cell' }">
        <span [ngSwitch]="cell.cid">
            <span *ngSwitchCase="1">
                <span class="grid-ddmr-cell-checkbox" [ngStyle]="{ 'background-image': getCheckValue(cell) }" (mousedown)="checkBoxClicked($event, cell)" (mouseup)="checkBoxMouseUp($event)"></span>
            </span>
            <span *ngSwitchDefault>
                <span class="grid-ddmr-cell-label">{{cell.text}}</span>
            </span>
        </span>
    </ng-template>
</iui-grid>
                            

Note A small time delay is required, because when drag drop finishes, the layout is updated and refreshed. However, the dragDrop event is fired before this, so that you can cancel it in your code (if required). To manually select rows, the selection must takes place after drop finishes and grid layout is fully updated.

Conclusion

Drag Drop of multiple rows in IntegralUI Grid component for Angular is straightforward. You only need to set multi selection active and allow drag drop operation to take place. As a result, you can select multiple rows, drag and drop them at new position. During this process, you can choose whether you want to move or copy the dragged rows at the target position, within the same Grid component.

The Grid component is part of IntegralUI Web.

Did you Like this Article?


Enter your e-mail address below and you will receive latest articles as well as news on upcoming events and special offers.