How can I help you?
Row Drag and Drop in Angular Grid Component
19 Mar 202624 minutes to read
The Syncfusion® Angular Grid component provides built-in support for seamless row drag and drop functionality. This feature enables effortless row rearrangement within the grid by dragging and dropping rows to new positions. Additionally, rows can be transferred between grids, as well as dragged and dropped to custom components, providing powerful flexibility for complex data management scenarios.
Key capabilities:
- Reorder rows within the same grid.
- Transfer rows between multiple grid instances.
- Drag rows to custom Angular components.
- Customize drag behavior with events and settings.
- Hide drag icons for seamless interaction.
To use the row drag and drop feature in Grid component, inject the RowDDService to the providers array. The RowDDService handles the row drag and drop functionality within the Grid component. Once the RowDD service is injected, use the allowRowDragAndDrop and targetID properties to enable and configure the row drag and drop feature in the Grid.
Drag and drop within the Grid
The drag and drop feature allows rearranging rows within the grid by dragging them using a drag icon. To activate this feature, set the allowRowDragAndDrop property to true.
The following example demonstrates drag and drop within the Grid:
import { orderDetails } from './datasource';
import { Component, OnInit } from '@angular/core';
import { GridModule, PageService, RowDDService, SelectionService, SelectionSettingsModel } from '@syncfusion/ej2-angular-grids';
@Component({
imports: [GridModule],
providers: [PageService, SelectionService, RowDDService],
standalone: true,
selector: 'app-root',
template: `<div class="control-section">
<ejs-grid [dataSource]='data' [allowRowDragAndDrop]='true'
[selectionSettings]='selectionOptions' height='335'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' width='120'
textAlign='Right'></e-column>
<e-column field='CustomerID' headerText='Customer ID' width='120'>
</e-column>
<e-column field='OrderDate' headerText='Order Date' width='100'
format="yMd" textAlign='Right'></e-column>
<e-column field='Freight' headerText='Freight' width='120' format='C2'
textAlign='Right'></e-column>
<e-column field='ShipCity' headerText='Ship City' width='130'>
</e-column>
<e-column field='ShipCountry' headerText='Ship Country' width='130'>
</e-column>
</e-columns>
</ejs-grid>
</div>`
})
export class AppComponent implements OnInit {
public data?: object[];
public selectionOptions?: SelectionSettingsModel;
ngOnInit(): void {
this.data = orderDetails;
this.selectionOptions = { type: 'Multiple' };
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Drag and drop to another Grid
The grid row drag and drop allows drag grid rows and drop to another grid. To enable this feature, set the allowRowDragAndDrop property to true in the source Grid component.
To specify the target Grid component where rows should be dropped, configure the rowDropSettings.targetID property. The targetID property references the “ID” of the destination Grid component.
The following example demonstrates row drag and drop between different Grid components:
import { data } from './datasource';
import { Component, OnInit } from '@angular/core';
import { GridModule, PageService, RowDDService, RowDropSettingsModel, SelectionService, SelectionSettingsModel } from '@syncfusion/ej2-angular-grids';
@Component({
imports: [ GridModule],
providers: [PageService, SelectionService, RowDDService],
standalone: true,
selector: 'app-root',
template: `<ejs-grid id='Grid' [dataSource]='data' [allowRowDragAndDrop]='true'
[rowDropSettings]='rowDropOptions' [selectionSettings]='selectionOptions'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right'
width=120></e-column>
<e-column field='CustomerID' headerText='Customer ID' width=150>
</e-column>
<e-column field='ShipCity' headerText='Ship City' width=150>
</e-column>
<e-column field='ShipName' headerText='Ship Name' width=150>
</e-column>
</e-columns>
</ejs-grid>
<ejs-grid id='DestGrid' [dataSource]='destGridData'
[allowRowDragAndDrop]='true' [rowDropSettings]='destRowDropOptions'
[selectionSettings]='selectionOptions'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right'
width=120></e-column>
<e-column field='CustomerID' headerText='Customer ID' width=150>
</e-column>
<e-column field='ShipCity' headerText='Ship City' width=150></e-column>
<e-column field='ShipName' headerText='Ship Name' width=150></e-column>
</e-columns>
</ejs-grid>`,
styleUrls: ['./app.style.css']
})
export class AppComponent implements OnInit {
public data?: object[];
public destGridData?: object[];
public rowDropOptions?: RowDropSettingsModel;
public destRowDropOptions?: RowDropSettingsModel;
public selectionOptions?: SelectionSettingsModel;
ngOnInit(): void {
this.data = data;
this.destGridData = [];
this.rowDropOptions = { targetID: 'DestGrid' };
this.destRowDropOptions = { targetID: 'Grid' };
this.selectionOptions = { type: 'Multiple' };
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
- Row drag and drop functionality is not supported with virtual scrolling and frozen rows and columns mode.
- The
RowDDServicemust be injected in the providers section.
Drag and drop to custom component
The Grid supports row drag-and-drop into custom components, enabling seamless data transfer without manual copy-paste. To enable this feature, set the allowRowDragAndDrop property to true and specify the target component’s “ID” in the targetID property of the rowDropSettings object.
In the following example, selected grid rows are dragged and dropped into a TreeView component using the rowDrop event. Upon successful drop, the corresponding grid row is removed and its data is inserted into the custom component:
import { sampleGridData } from './datasource';
import { Component, OnInit, ViewChild } from '@angular/core';
import { GridComponent, GridModule, PageService, RowDDService, RowDragEventArgs, SelectionService } from '@syncfusion/ej2-angular-grids';
import { TreeGridAllModule, TreeGridComponent } from '@syncfusion/ej2-angular-treegrid';
import { isNullOrUndefined } from '@syncfusion/ej2-base';
@Component({
imports: [GridModule, TreeGridAllModule],
providers: [PageService, SelectionService, RowDDService],
standalone: true,
selector: 'app-root',
template: ` <ejs-grid #grid id='Grid' [dataSource]='sourceData' [allowPaging]="true"
[pageSettings]="true" [allowSelection]="true" [allowRowDragAndDrop]="true"
[selectionSettings]="selectionOptions" [rowDropSettings]="srcDropOptions"
(rowDrop)='onRowDrop($event)' [editSettings]="gridEditSettings">
<e-columns>
<e-column field='taskID' headerText='Task ID' textAlign='Right'
width=90></e-column>
<e-column field='taskName' headerText='Task Name' textAlign='Left'
width=180></e-column>
<e-column field='description' headerText='Description'
textAlign='Left' width=180></e-column>
<e-column field='category' headerText='Category'
textAlign='Left' width=180></e-column>
<e-column field='startDate' headerText='Start Date' textAlign='Right'
format='yMd' width=120></e-column>
<e-column field='duration' headerText='Duration' textAlign='Right'
width=80></e-column>
</e-columns>
</ejs-grid>
<ejs-treegrid #treegrid id='TreeGrid'
childMapping='subtasks' [editSettings]='treeGridEditSettings'>
<e-columns>
<e-column field='taskID' headerText='Task ID' textAlign='Right'
width=90></e-column>
<e-column field='taskName' headerText='Task Name' textAlign='Left'
width=180></e-column>
<e-column field='startDate' headerText='Start Date' textAlign='Right'
format='yMd' width=90></e-column>
<e-column field='duration' headerText='Duration' textAlign='Right'
width=80></e-column>
</e-columns>
</ejs-treegrid>`
})
export class AppComponent implements OnInit {
@ViewChild('grid')
gridObject!: GridComponent;
@ViewChild('treegrid')
treeGridObject!: TreeGridComponent;
public sourceData: Object[] = [];
public selectionOptions?: Object;
public srcDropOptions?: Object;
public treegridData: object[] = [];
public gridEditSettings?:Object;
public treeGridEditSettings?:Object;
ngOnInit(): void {
this.sourceData = sampleGridData;
this.selectionOptions = { type: 'Multiple' };
this.srcDropOptions = { targetID: 'TreeGrid' };
this.gridEditSettings = { allowDeleting: true };
this.treeGridEditSettings = { allowAdding: true, allowEditing: true };
}
onRowDrop(args:RowDragEventArgs) {
if ((args.target as Element).closest('.e-treegrid')) {
args.cancel = true;
var rowIndex = !isNullOrUndefined((args.target as Element).closest('.e-row') as Element)
? ((args.target as HTMLElement).closest('.e-row') as any).rowIndex
: 0;
for (var i = 0; i < (args.data as Object[]).length; i++) {
this.treeGridObject.addRecord((args.data as Object[])[i] , rowIndex);
this.gridObject.deleteRecord('taskID', (args.data as Object[])[i]);
}
}
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));The
rowDropevent triggers when a row is dropped onto a custom component, regardless of drop success. Use theargs.cancelproperty to prevent the default action and implement custom handling logic.
Hide drag and drop icons
By default, the Syncfusion® Angular Grid displays drag icon in each row when enabling the row drag and drop feature. To hide these icons, set the targetID property of the rowDropSettings object to the current Grid’s ID.
When targetID references the Grid’s own ID, the Grid renders without drag helper icons. Customize drag and drop behavior by binding to the rowDrop event. Within the event handler, prevent the default action by setting args.cancel to true, then reorder rows using the reorderRows method.
The following example demonstrates hide drag and drop icons in the Syncfusion® angular Grid:
import { data } from './datasource';
import { Component, ViewChild } from '@angular/core';
import { GridComponent, GridModule, RowDDService, RowDragEventArgs, SelectionService } from '@syncfusion/ej2-angular-grids';
@Component({
imports: [ GridModule],
providers: [SelectionService, RowDDService],
standalone: true,
selector: 'app-root',
template: `<div class="control-section">
<ejs-grid #grid [dataSource]="data" [allowRowDragAndDrop]="true"
[selectionSettings]="selectOptions" [rowDropSettings]="rowDropOptions"
id="Grid" (rowDrop)="rowDrop($event)">
<e-columns>
<e-column field="OrderID" headerText="Order ID" width="120"
textAlign="Right"></e-column>
<e-column field="CustomerID" headerText="Customer Name"
width="130"></e-column>
<e-column field="OrderDate" headerText="Order Date" width="120"
format="yMd" textAlign="Right"></e-column>
<e-column field="Freight" headerText="Freight" width="120"
format="C2" textAlign="Right"></e-column>
<e-column field="ShipCity" headerText="Ship City" width="130">
</e-column>
<e-column field="ShipCountry" headerText="Ship Country"
width="130"></e-column>
</e-columns>
</ejs-grid>
</div>`
})
export class AppComponent {
public data: Object[] = [];
public selectOptions?: Object;
public rowDropOptions?: object;
@ViewChild('grid') public grid?: GridComponent;
ngOnInit(): void {
this.data = data;
this.selectOptions = { type: 'Multiple' };
this.rowDropOptions = { targetID: 'Grid' };
}
rowDrop(args:RowDragEventArgs) {
args.cancel = true;
var value = [];
for (var r = 0; r < (args.rows as Element[]).length; r++) {
value.push((args.fromIndex as number) + r);
}
(this.grid as GridComponent).reorderRows(value, (args.dropIndex as number));
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
- The selection feature must be enabled to allow users to select rows before performing drag and drop operations.
- For multiple row selection, set the type property to
Multiple. Users can then select multiple rows by clicking and dragging within the grid.
Drag and drop events
The Grid component provides powerful events that trigger during row drag and drop operations. These events enable customization of drag elements, tracking of drag progress, and execution of actions when rows are dropped on target elements. The following events are available:
-
rowDragStartHelper: Triggers when clicking on the drag icon or grid row, allowing customization of the drag element based on specific criteria.
-
rowDragStart: Triggers when grid row dragging begins, providing opportunity to initialize drag-specific logic.
-
rowDrag: Triggers continuously while the grid row is being dragged, enabling real-time feedback and validation.
-
rowDrop: Triggers when a drag element is dropped onto a target element, allowing custom drop handling and data manipulation.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, SelectionService, RowDDService } from '@syncfusion/ej2-angular-grids'
import { Component, ViewChild,OnInit } from '@angular/core';
import { GridComponent, RowDragEventArgs } from '@syncfusion/ej2-angular-grids';
import { orderDetails, columnDataType } from './datasource';
@Component({
imports: [ GridModule],
providers: [SelectionService, RowDDService],
standalone: true,
selector: 'app-root',
template: `<div style="text-align:center">
<p style="color:red;" id="message">{{ message }}</p>
</div>
<ejs-grid #grid [dataSource]="data" [allowPaging]="true"
[allowRowDragAndDrop]="true" (rowDragStartHelper)="rowDragStartHelper($event)"
[selectionSettings]="selectOptions"
id="Grid" (rowDrop)="rowDrop($event)" (rowDragStart)="rowDragStart($event)"
(rowDrag)="rowDrag($event)">
<e-columns>
<e-column field="OrderID" headerText="Order ID" width="120"
textAlign="Right"></e-column>
<e-column field="CustomerID" headerText="Customer Name"
width="130"></e-column>
<e-column field="OrderDate" headerText="Order Date" width="120"
format="yMd" textAlign="Right"></e-column>
<e-column field="Freight" headerText="Freight" width="120"
format="C2" textAlign="Right"></e-column>
<e-column field="ShipCity" headerText="Ship City" width="120">
</e-column>
<e-column field="ShipCountry" headerText="Ship Country"
width="120"></e-column>
</e-columns>
</ejs-grid>`,
styleUrls: ['./app.style.css']
})
export class AppComponent implements OnInit {
public data: Object[] = [];
public selectOptions?: Object;
public message?: string;
@ViewChild('grid')
public grid!: GridComponent;
ngOnInit(): void {
this.data = orderDetails;
this.selectOptions = { type: 'Multiple' };
}
rowDragStartHelper(args: RowDragEventArgs): void {
this.message = `rowDragStartHelper event triggered`;
if (((args.data as Object[])[0] as columnDataType).OrderID === 10248) {
args.cancel = true;
}
}
rowDragStart(args: RowDragEventArgs) {
this.message = `rowDragStart event triggered`;
args.cancel = true;
}
rowDrag(args:RowDragEventArgs): void {
this.message = `rowDrag event triggered`;
(args.rows as Element[]).forEach((row: Element) => {
row .classList.add('drag-limit');
});
}
rowDrop(args: RowDragEventArgs): void {
this.message = `rowDrop event triggered`;
const value = [];
for (let r = 0; r < (args.rows as Element[]).length; r++) {
value.push((args.fromIndex as number) + r);
}
this.grid.reorderRows(value, (args.dropIndex as number));
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Limitations
The row drag and drop feature offers focused functionality, working seamlessly with a curated set of Grid features. The features listed below are not part of its supported set of features:
- Row template
- Detail template
- Hierarchy grid
- Row pinning
- Virtual scrolling beyond the grid viewport