Drag and Drop Multiple Items in Angular ListBox

Created: 22 Jan 2019

When drag and drop is enabled in ListBox component for Angular, you can move items one by one within the same or to other components. With multi selection enabled you can also drag and drop multiple items at the same. This article explains how to do that.

ListBox 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 this demo, you can select multiple items by holding CTRL or SHIFT key and clicking on items in the ListBox. Next, by holding the left mouse button and dragging the mouse cursor starting from a selected item, a drag and drop operation will start in which all selected items are carried. On drop, all dragged items are placed at target location.

Note For demonstration purposes only, you cannot select the top three items.

To create a copy of dragged items, on drop hold the SHIFT key. In this way, instead of original items, copies are created and dropped at target position. This allows you to choose whether you want to move or copy multiple items during drag drop.

How to Drag and Drop Multiple Items

At first, you need to enable drag and drop in the angular ListBox by setting the allowDrag property to true. This only allows you to drag items one by one. To enable drag and drop for multiple items, you also need to set the selectionMode property to one of these values:

  • MultiSimple - you can select items by single click
  • MultiExtended - you can select items by left-click and CTRL or SHIFT key pressed
import { Component, enableProdMode, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core';
import { IntegralUISelectionMode } from './integralui/components/integralui.core';

enableProdMode();

@Component({
    selector: 'iui-app',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild('application', {read: ViewContainerRef}) applicationRef: ViewContainerRef;

    public items: Array;
    public selMode: IntegralUISelectionMode = IntegralUISelectionMode.MultiExtended;
}
                            
<div class="app-block" #application>
    <iui-listbox [appRef]="applicationRef" [items]="items" [controlStyle]="listStyle" [allowDrag]="true" [selectionMode]="selMode" (dragOver)="listDragOver($event)" #listbox>
        <iui-listitem *ngFor="let item of items" [controlStyle]="itemStyle" [allowAnimation]="true">  
            <div class="lbox-dd-multi-item-content">
                <span class="lbox-dd-multi-icons {{item.icon}}"></span>
                <span class="lbox-dd-multi-title">{{item.text}}</span>
                <span class="lbox-dd-multi-year">{{item.year}}</span>
                <iui-rating [controlStyle]="lboxOverviewRatingStyleStars" [value]="getRating(item.rating)" [max]="5"></iui-rating>
            </div>
        </iui-listitem>
    </iui-listbox>
</div>
                            

Related: Selection Options in Angular ListBox

On correlation with custom action set in dragOver event handler (see below), to create a scenario where drag and drop is allowed only form items that are below the first three. The first three items are marked as non selectable.

constructor(){
    this.items = [
        { id: 1, icon: "sci-fi", allowDrag: false, canSelect: false, text: "Star Trek", year: "2009", rating: 8.0 },
        { id: 2, icon: "adventure", allowDrag: false, canSelect: false, text: "Cast Away", year: "2000", rating: 7.7, style: { color: 'red' }  },
        { id: 3, icon: "action", allowDrag: false, canSelect: false, text: "Gladiator ", year: "2000", rating: 8.5 },
        { id: 4, icon: "drama", text: "Malèna", year: "2000", rating: 7.5 },
        { id: 5, icon: "music", text: "Moulin Rouge", year: "2001", rating: 7.6 },
        { id: 6, icon: "comedy", text: "Snatch", year: "2000", rating: 8.3  },
        { id: 7, icon: "biography", text: "A Beautiful Mind", year: "2001", rating: 8.2  },
        { id: 8, icon: "crime", text: "Black Hawk Down", year: "2001", rating: 7.7 },
        { id: 9, icon: "western", text: "Django Unchained", year: "2012", rating: 8.5  },
        { id: 10, icon: "sci-fi", text: "Man of Steel", year: "2013", rating: 7.2 },
        { id: 11, icon: "horror", text: "The Ring", year: "2002", rating: 7.1 },
        { id: 12, icon: "romance", text: "40 Days and 40 Nights", year: "2002", rating: 5.6 },
        { id: 13, icon: "sci-fi", text: "Minority Report", year: "2002", rating: 7.7 },
        { id: 14, icon: "comedy", text: "Scary Movie 3", year: "2003", rating: 5.5 },
        { id: 15, icon: "music", text: "Walk the Line", year: "2005", rating: 7.9  },
        { id: 16, icon: "romance", text: "How to Lose a Guy in 10 Days", year: "2003", rating: 6.4 },
        { id: 17, icon: "crime", text: "The Dark Knight", year: "2008", rating: 9.0  },
        { id: 18, icon: "horror", text: "American Psycho", year: "2000", rating: 7.6 },
        { id: 19, icon: "drama", text: "The Grand Budapest Hotel", year: "2014", rating: 8.1 },
        { id: 20, icon: "comedy", text: "The Wolf of Wall Street", year: "2013", rating: 8.2 }
    ];
}
                            

Handling the dragOver Event during Multi Drag Drop

Whenever an item or multiple items are dragged over other items, the dragOver event will fire. You can intercept this event in your code and provide custom conditions. Depending on condition set, you can choose whether to continue or cancel the drag and drop operation.

Related: Drag and Drop Events in ListBox

In case when multiple items are dragged, the dragOver event data holds an array of all selected items. You can check this data in your event handler:

listDragOver(e: any){
    if (e.dragItem && Array.isArray(e.dragItem)){
        let targetIndex = this.items.indexOf(e.targetItem);
        if (targetIndex <= 2)
            e.cancel = true;
    }
}
                            
<div class="app-block" #application>
    <iui-listbox [appRef]="applicationRef" [items]="items" [controlStyle]="listStyle" [allowDrag]="true" [selectionMode]="selMode" (dragOver)="listDragOver($event)" #listbox>
        <iui-listitem *ngFor="let item of items" [controlStyle]="itemStyle" [allowAnimation]="true">  
            <div class="lbox-dd-multi-item-content">
                <span class="lbox-dd-multi-icons {{item.icon}}"></span>
                <span class="lbox-dd-multi-title">{{item.text}}</span>
                <span class="lbox-dd-multi-year">{{item.year}}</span>
                <iui-rating [controlStyle]="lboxOverviewRatingStyleStars" [value]="getRating(item.rating)" [max]="5"></iui-rating>
            </div>
        </iui-listitem>
    </iui-listbox>
</div>
                            

As you can see, a check to the e.dragItem field is set to determine whether it is an array or a single object. Depending on this value, you can proceed with the event by adding custom code.

For example, you can check whether the target item is a valid one and whether the drop position is ok. In this code, the drag and drop is allowed only if the target item is below the top three items. In this way, the first three items can act as fixed ones, while you can reorder all the other items. If the target item is one of these top three items, you can cancel the drag and drop by setting the e.cancel data field to true.

Related: Drag and Drop between ListBox and ListView

In this way whenever you drag items over top three items, the mouse cursor will change to NO DROP, stating that you cannot drop items at that location. In addition, top three items are also disabled from dragging, by simple setting their allowDrag field to false.

Conclusion

Drag and Drop feature of Angular ListBox component allows you to reorder items within the component itself during run-time. If multi selection is enabled, you can drag and drop multiple items at once and place them at different position. In this process, you can add event handlers with your own custom conditions that may alter the drag and drop operation.

The ListBox 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.