Drag and Drop Events in Angular List View

Created: 23 Jan 2019

During item drag and drop in IntegralUI ListView for Angular, based on user action several drag and drop events can occur. You can handle these events in your code and provide additional actions that may alter the default drag and drop functionality. In following sections of this article you will learn about drag drop events that are supported and how to handle them in different situations.

ListView 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

As item is dragged in the ListView, the list on the right side will display event when fired. At the top of the list will be the last event fired. As explained in sections below, when item is dragged over target item "Moulin Rouge" the drag and drop is cancelled. In other cases, you can freely reorder items.

The event log below displays events that fires during drag drop. If the same event is fired more than once, mostly happens on drag over at the same drop position, the counter left from the event name will state how many times that event fired.

Drag and Drop Events in Angular List View

The following drag and drop events are supported:

  • dragEnter - fires when entering the List View space while dragging an item
  • dragDrop - fires on item drop
  • dragLeave - fires when leaving the List View space while dragging an item
  • dragOver - fires while dragging an item over target item or component

You can handle these events in your code, place custom conditions that will determine whether item will drop or not.

Event Data

Each drag and drop event carries data with information on source, target, drop position etc. that you can use in your code to customize the drag drop operations in part or completely and create the best solution for your application requirements. Depending on the event, a different data is included. Here is a list of data fields available:

  • action - it can be move or copy
  • cancel - if true the drag and drop is cancelled
  • dragItem - specifies an item(s) that is dragged
  • dropPos - current position at which dragged item can drop
    • 1 - item will drop above target item
    • 2 - item will drop below target item
    • -1 - item will drop at the end of the list
  • event - general HTML5 drag and drop event data
  • isDropAllowed - determines whether item is allowed to drop
  • mousePos - mouse position in page coordinates
  • sourceCtrl - a reference to the source component from where the item is dragged
  • targetCtrl - a reference to the target component over which the item can drop
  • targetItem - specifies the target item over which the dragged item can drop

The sourceCtrl and targetCtrl fields may contain references to components that are not a ListView. For example, it can be a Grid, ListBox, TreeGrid , TreeView or any other angular component. This means that List View can accept objects to drop over its space that are not items.

How to Handle the Drag Over Event in ListView

Whenever item is dragged over the angular ListView component, the dragOver event fires. You can handle this event and intercept the drag drop in process with your own custom conditions that may cancel the event.

For example, let's say that if the target item is "Moulin Rouge, and you don't want to drop the dragged item over it. In this case, you can cancel the whole process by:

  1. Checking the targetItem field in event data whether it is the one named above
  2. Set the cancel field of the event data to true
listDragOver(e: any){
    if (e.targetItem && e.targetItem.text == 'Moulin Rouge')
        e.cancel = true;
}
                            
<div class="app-block" #application>
    <iui-listview [appRef]="applicationRef"  [items]="items" [controlStyle]="ctrlStyle" [allowDrag]="true" (selectionChanged)="itemSelectionChanged($event)" (dragEnter)="listDragEnter($event)" (dragOver)="listDragOver($event)" (dragLeave)="listDragLeave($event)" (dragDrop)="listDragDrop($event)" #listview>
        <iui-listitem *ngFor="let item of items; let i = index" [controlStyle]="itemStyle">
            <div class="lview-dd-evnt-custom-item-large" (mouseenter)="hoverItem=item" (mouseleave)="hoverItem=null">
                <span *ngIf="item == currentSelection" class="lview-dd-evnt-corner"></span>
                <span class="lview-dd-evnt-num-corner">{{i+1}}</span><br />
                <div class="lview-dd-evnt-icon-large">
                    <span class="lview-dd-evnt-icons {{item.icon}}"></span>
                </div><br />
                <span class="lview-dd-evnt-title-large">{{item.text}}</span><br />
                <iui-rating [controlStyle]="lViewRatingStyle" [(ngModel)]="item.rating" [max]="5" [division]="2"></iui-rating>
            </div>
        </iui-listitem>
    </iui-listview>
    <div class="app-event-block">
        <button (click)="clearEventLog()">Clear</button>
        <p>Event log:</p>
        <ul class="app-event-log">
            <li *ngFor="let ev of eventLog">
                <span *ngIf="ev.count" class="app-event-count">{{ev.count}}</span> <span class="app-event-name">{{ev.name}}</span>
                {{ev.info}}<span class="app-event-value"> at position: {{ev.position}}</span> <span *ngIf="ev.cancelled" class="app-event-cancelled">cancelled</span>
            </li>
        </ul>
    </div>
</div>
                            

Note Note You can also prevent item to drop over specified item by setting the allowDrop field of the target item object to false.

You can add other kinds of conditions, based on the event data. For example, you can use the drop position, whether action is drag move or drag copy, single or multiple items are dragged etc.

Cancelling Drag and Drop Events

To cancel a drag and drop event is simple. You can do it within the handler function for dragOver or dragDrop event, where you can set the cancel field of the event data to true. When mouse button is released nothing will happen, there will be no change to the items structure.

listDragOver(e: any){
    e.cancel = true;
}
                            

The above code will cancel the drag and drop in all cases. This is same as if you set the allowDrop property of the angular ListView component to false.

It will be more useful to add some conditions, that if fulfilled will cancel the item drag drop. For example, like it is explained in previous section by checking first if the target item is valid or not. The more suitable case for cancelling a drop event is to set it if some action required was not yet completed, like update of the server data is not yet finished.

In addition, it is useful to cancel the item drop in whole when you want to change the item data on your own. In this case, you need to manually complete the drag and drop by placing the dropped item at target location in code.

listDragDrop(e: any){
    e.cancel = true;

    if (e.dragItem){
        // Remove the item from the source component
        e.sourceCtrl.removeItem(e.dragItem);

        // Add the item to target component at location, depending on drop position
        switch (e.dropPos){
            case 1: // Above/Left from target item
                e.targetCtrl.insertItemBefore(e.dragItem, e.targetItem);
                break;

            case 2: // Below/Right from target item
                e.targetCtrl.insertItemAfter(e.dragItem, e.targetItem);
                break;

            default: // At the end of the list
                e.targetCtrl.addItem(e.dragItem);
                break;
        }

        // Update the layout of the target component
        e.targetCtrl.updateLayout();
    }
}
                            
<div class="app-block" #application>
    <iui-listview [appRef]="applicationRef"  [items]="items" [controlStyle]="ctrlStyle" [allowDrag]="true" (selectionChanged)="itemSelectionChanged($event)" (dragEnter)="listDragEnter($event)" (dragOver)="listDragOver($event)" (dragLeave)="listDragLeave($event)" (dragDrop)="listDragDrop($event)" #listview>
        <iui-listitem *ngFor="let item of items; let i = index" [controlStyle]="itemStyle">
            <div class="lview-dd-evnt-custom-item-large" (mouseenter)="hoverItem=item" (mouseleave)="hoverItem=null">
                <span *ngIf="item == currentSelection" class="lview-dd-evnt-corner"></span>
                <span class="lview-dd-evnt-num-corner">{{i+1}}</span><br />
                <div class="lview-dd-evnt-icon-large">
                    <span class="lview-dd-evnt-icons {{item.icon}}"></span>
                </div><br />
                <span class="lview-dd-evnt-title-large">{{item.text}}</span><br />
                <iui-rating [controlStyle]="lViewRatingStyle" [(ngModel)]="item.rating" [max]="5" [division]="2"></iui-rating>
            </div>
        </iui-listitem>
    </iui-listview>
    <div class="app-event-block">
        <button (click)="clearEventLog()">Clear</button>
        <p>Event log:</p>
        <ul class="app-event-log">
            <li *ngFor="let ev of eventLog">
                <span *ngIf="ev.count" class="app-event-count">{{ev.count}}</span> <span class="app-event-name">{{ev.name}}</span>
                {{ev.info}}<span class="app-event-value"> at position: {{ev.position}}</span> <span *ngIf="ev.cancelled" class="app-event-cancelled">cancelled</span>
            </li>
        </ul>
    </div>
</div>
                            

This is more suitable for updating the client data in the List View after that server data is updated.

Conclusion

Drag and Drop functionality in IntegralUI ListView component for Angular accompanies few drag and drop events. Each event carries data that includes the source, target, position, whether action is move or copy operation etc. By handling these events in your code, you can alter the drag and drop process in part or completely using custom conditions. In some cases, you may even cancel the whole drag and drop operation.

The ListView component is part of IntegralUI Web.

Newsletter


Sign-up to our newsletter and you will receive news on upcoming events, latest articles, samples and special offers.
Name: Email: *
*By checking this box, I agree to receive a newsletter from Lidor Systems in accordance with the Privacy Policy. I understand that I can unsubscribe from these communications at any time by clicking on the unsubscribe link in all emails.