Grid Row Drag

In Ignite UI for Angular Grid, RowDrag is initialized on the root igx-grid component and is configurable via the rowDraggable input. Enabling row dragging provides users with a row drag-handle with which they can initiate dragging of a row.

Demo


Configuration

In order to enable row-dragging for your igx-grid, all you need to do is set the grid's rowDraggable to true. Once this is enabled, a row-drag handle will be displayed on each row. This handle can be used to initiate row dragging.

<igx-grid [rowDraggable]="true">
 ...
</igx-grid>

Clicking on the drag-handle and moving the cursor while holding down the button will cause the grid's onRowDragStart event to fire. Releasing the click at any time will cause onRowDragEnd event to fire.

Below, you can find a walkthrough on how to configure an igx-grid to support row dragging and how to properly handle the drop event.

In this example, we'll handle dragging a row from one grid to another, removing it from the first data source and adding it to the second.

Drop Areas

Enabling row-dragging was pretty easy, but now we have to configure how we'll handle row-dropping. We can define where we want our rows to be dropped using the igxDrop directive.

First we need to import the IgxDragDropModule in our app module:

import { ..., IgxDragDropModule } from 'igniteui-angular';
...
@NgModule({
    imports: [..., IgxDragDropModule]
})

Then, in our template, we define a drop-area using the directive's selector:

In this case, our drop-area will be a whole second grid where we'll drop the rows.

<igx-grid #targetGrid igxDrop [data]="data2" [autoGenerate]="false" [emptyGridTemplate]="dragHereTemplate"
    (enter)="onEnterAllowed($event)" (leave)="onLeaveAllowed($event)" (dropped)="onDropAllowed($event)" [primaryKey]="'ID'">
    ...
</igx-grid>

Since the grid will initially be empty, we also define a template that will be more meaningful to the user:

<ng-template #dragHereTemplate>
    Drop a row to add it to the grid
</ng-template>

You may enable animation when a row is dropped on a non-droppable area using the animation parameter of the onRowDragEnd event. If set to true, the dragged row will animate back to its' original position when dropped over a non-droppable area.

You may enable animation like this:

export class IgxGridRowDragComponent {
    ...
    public onRowDragEnd(args) {
        args.animation = true;
    }

}

Drop Area Event Handlers

Once we've defined our drop-area in the template, we have to declare our handlers for the igxDrop's enter, leave and dropped events in our component's .ts file.

First, let's take a look at our enter and leave handlers. In those methods, we just want to change the icon of the drag's ghost so we can indicate to the user that they are above an area that allows them to drop the row:

export class IgxGridRowDragComponent {
    ...
    public onEnterAllowed(args) {
        this.changeGhostIcon(args.drag.ghostElement, DragIcon.ALLOW);
    }

    public onLeaveAllowed(args) {
        this.changeGhostIcon(args.drag.ghostElement, DragIcon.DEFAULT);
    }

    private changeGhostIcon(ghost, icon: string) {
        if (ghost) {
            const currentIcon = ghost.querySelector(".igx-grid__drag-indicator  > igx-icon");
            if (currentIcon) {
                currentIcon.innerText = icon;
            }
        }
    }

}

The changeGhostIcon private method just changes the icon inside of the drag ghost. The logic in the method finds the element that contains the icon (using the igx-grid__drag-indicator class that is applied to the drag-indicator container), changing the element's inner text to the passed one. The icons themselves are from the material font set and are defined in a separate enum:

enum DragIcon {
    DEFAULT = "drag_indicator",
    ALLOW = "add"
}

Next, we have to define what should happen when the user actually drops the row inside of the drop-area.

export class IgxGridRowDragComponent {
    @ViewChild("sourceGrid", { read: IgxGridComponent }) public sourceGrid: IgxGridComponent;
    @ViewChild("targetGrid", { read: IgxGridComponent }) public targetGrid: IgxGridComponent;
    ... 
    public onDropAllowed(args) {
        this.targetGrid.addRow(args.dragData.rowData);
        this.sourceGrid.deleteRow(args.dragData.rowID);
    }
    ...
}

We define a reference to each of our grids via the ViewChild decorator and the handle the drop as follows:

  • add a row to the targetGrid that contains the data of the row being dropped
  • remove the dragged row from the sourceGrid
Note

When using row data from the event arguments (args.dragData.rowData) or any other row property, note that the entire row is passed in the arguments as a reference, which means that you must clone the data you need, if you want to distinguish it from the one in the source grid.

Templating the drag ghost

The drag ghost can be templated using the IgxRowDragGhost directive, applied to a <ng-template> inside of the igx-grid's body:

<igx-grid>
...
   <ng-template igxRowDragGhost>
        <div>
            <igx-icon fontSet="material">arrow_right_alt</igx-icon>
        </div>
    </ng-template>
...
</igx-grid>

The result of the configuration can be seem below in a igx-grid with row dragging and multiple selection enabled. The demo shows the count of the currently dragged rows:

Example Demo

Templating the drag icon

The drag handle icon can be templated using the grid's dragIndicatorIconTemplate. In the example we're building, let's change the icon from the default one (drag_indicator) to drag_handle. To do so, we can use the igxDragIndicatorIcon to pass a template inside of the igx-grid's body:

<igx-grid>
...
    <ng-template igxDragIndicatorIcon>
        <igx-icon>drag_handle</igx-icon>
    </ng-template>
...
</igx-grid>

Once we've set the new icon template, we also need to adjust the DEFAULT icon in our DragIcon enum, so it's properly change by the changeIcon method:

enum DragIcon {
    DEFAULT = "drag_handle",
    ...
}

Once our drop handlers are properly configured, we're good to go! The result of the configuration can be seem below:

Example Demo

The following sample demonstrates how to configure row reordering in the grid. Holding onto the drag icon will allow you to move a row anywhere in the grid.


Application Demo

The following demo demonstrates how to use row drag event information to change both states of a custom component, where the row is dropped, and the source grid itself. Try to drag moons from the grid and drop them to their corresponding planets. Row drag ghost background is dynamically changed, depending on the hovered planet. If you succeed then the row in the grid will be selected and dragging will be disabled for it. Clicking planets will give you useful information.


Note

The classes applied to the row drag ghost, used in the demo above, are using ::ng-deep modifier, because row drag is an internal grid feature and cannot be accessed on application level, due to the CSS encapsulation.

Limitations

Currently, there are no known limitations for the rowDraggable directive.

API References

Additional Resources

Our community is active and always welcoming to new ideas.