PrimeNG Drag And Drop Example
Overview
Using PrimeNG Drag and Drop, we can be get hold of an object and move it to a different location. This ability to move objects help us make the UI more interactive. Using PrimeNG implementing the Drag and Drop functionality is very easy. pDraggable and pDroppable are attached to a target element to add drag-drop behavior.We will be implementing a functionality where a user can create a list of his favorite books from the available books. He can drag a book from the available books section to the favorite books section.
Technology Stack
We will be making use of-- Angular 8
- PrimeNG
Video Tutorial
Table Of Contents :
Implementation
For this tutorial series we make use of Visual Studio CodeThe Angular project we will be developing is as follows-
Develop Angular Application
- Install NodeJS. Go to NodeJS downloads page and download installer. Start the installer and install nodejs.
-
Install angular cli using the command-
npm install -g @angular/cli
-
Create new Angular Project named drg example
ng new dragexample --skip-git
-
Go inside the created the created angular project and start Angular Project-
ng serve
-
Go to localhost:4200
Use PrimeNG Components
-
Install PrimeNG
npm install primeng --save
-
Install Prime Icons
npm install primeicons --save
-
Install Font Awesome
npm install font-awesome --save
-
Install Angular CDK
npm install @angular/cdk --save
-
If we now go to package.json, we will see the following primeng dependencies
-
Open the angular.json and add the following in the styles section
"./node_modules/primeicons/primeicons.css", "./node_modules/primeng/resources/themes/nova-light/theme.css", "./node_modules/primeng/resources/primeng.min.css",
ng generate component drg
In the app-routing.module.ts add the route as drg for our new DrgComponent
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { DrgComponent } from './drg/drg.component';
const routes: Routes = [
{ path: 'drg', component: DrgComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
<router-outlet></router-outlet>
Start the application using-
ng serve
If we now go to localhost:4200/drg we see the following-
Adding the PrimeNG Component in Angular Application
For adding any PrimeNG Component in Angular we will be following below steps--
Add the following PrimeNG modules to the app.module.ts
- DragDropModule
- PanelModule
- TableModule
- HttpClientModule
- BrowserAnimationsModule
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { DrgComponent } from './drg/drg.component'; import { DragDropModule } from 'primeng/dragdrop'; import { PanelModule } from 'primeng/panel'; import { TableModule } from 'primeng/table'; import { HttpClientModule } from '@angular/common/http'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @NgModule({ declarations: [ AppComponent, DrgComponent ], imports: [ BrowserModule, AppRoutingModule, DragDropModule, PanelModule, TableModule, HttpClientModule, BrowserAnimationsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
-
Create a service named BookService
ng generate service service/book
-
Create the Book domain object
export interface Book { name?; price?; author?; serialNo? }
-
We will be having 2 JSON files in the assets folder -
-
all-books.json
{ "data": [ { "name": "Harry Potter and the Deathly Hallows", "price": 20, "author": "J.K. Rowling ", "serialNo": "154" }, { "name": "Song Of Ice and Fire", "price": 20, "author": "R.R. Martin", "serialNo": "155" } ] }
-
favorite-books.json
{ "data": [ { "name": "The Godfather", "price": 10, "author": "Mario Puzo", "serialNo": "152" }, { "name": "The Fellowship of the Ring", "price": 15, "author": "J.R.R. Tolkien", "serialNo": "153" } ] }
import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Book } from './book'; @Injectable({ providedIn: 'root' }) export class BookService { constructor(private http: HttpClient) { } getAllBooks() { return this.http.get<any>('assets/all-books.json') .toPromise() .then(res => <Book[]>res.data) .then(data => { return data; }); } getFavoriteBooks() { return this.http.get<any>('assets/favorite-books.json') .toPromise() .then(res => <Book[]>res.data) .then(data => { return data; }); } }
-
all-books.json
-
Next in the DrgComponent we will be creating the backing data by calling the BookService
getAllBooks and getFavoriteBooks.
import { Component, OnInit } from '@angular/core'; import { BookService } from '../service/book.service'; import { Book } from '../service/book'; @Component({ selector: 'app-drg', templateUrl: './drg.component.html', styleUrls: ['./drg.component.css'] }) export class DrgComponent implements OnInit { availableBooks: Book[]; favoriteBooks: Book[]; draggedBook: Book; constructor(private bookService: BookService) { } ngOnInit() { this.bookService.getAllBooks().then(books => this.availableBooks = books); this.bookService.getFavoriteBooks().then(books => this.favoriteBooks = books); console.log(this.availableBooks); } dragStart(event, book: Book) { this.draggedBook = book; } drop(event) { if (this.draggedBook) { let draggedBookIndex = this.findIndex(this.draggedBook); this.favoriteBooks = [...this.favoriteBooks, this.draggedBook]; this.availableBooks = this.availableBooks.filter((val, i) => i != draggedBookIndex); this.draggedBook = null; } } dragEnd(event) { this.draggedBook = null; } findIndex(book: Book) { let index = -1; for (let i = 0; i < this.availableBooks.length; i++) { if (book.name === this.availableBooks[i].name) { index = i; break; } } return index; } }
-
Finally in the drg component html file we will be using the created backing data -
availableBooks and favoriteBooks for the drag and drop functionality.
Also it is important to keep name of pDraggable and pDroppable to be the same.
In our case we have used the name books.
Also in the assets folder we will need to provide the images with the serial number as the name.<div class="p-grid"> <h1>List Of Available Books</h1> <div class="p-col-12 p-md-6 p-col-nogutter drag-column"> <div *ngFor="let book of availableBooks" class="ui-helper-clearfix"> <div class="ui-g-12 ui-md-4" pDraggable="books" (onDragStart)="dragStart($event, book)" (onDragEnd)="dragEnd($event)"> <p-panel [header]="book.name" [style]="{'text-align':'center'}"> <img src="assets/images/{{book.serialNo}}.PNG"> </p-panel> </div> </div> </div> <h1>My Personal Favorites</h1> <div class="p-col-12 p-md-6 drop-column" pDroppable="books" (onDrop)="drop($event)" [ngClass]="{'ui-highlight-book':draggedBook}"> <p-table [value]="favoriteBooks"> <ng-template pTemplate="header"> <tr> <th>Name</th> <th>Price(Dollars)</th> <th>Author</th> </tr> </ng-template> <ng-template pTemplate="body" let-book> <tr> <td>{{book.name}}</td> <td>{{book.price}}</td> <td>{{book.author}}</td> </tr> </ng-template> </p-table> </div> </div>