UNPKG

ng2-dnd

Version:

Angular 2 Drag-and-Drop without dependencies

419 lines (371 loc) 14.1 kB
Angular 2 Drag-and-Drop [![Build Status](https://travis-ci.org/akserg/ng2-dnd.svg?branch=master)](https://travis-ci.org/akserg/ng2-dnd) [![npm version](https://img.shields.io/npm/v/ng2-dnd.svg)](https://www.npmjs.com/package/ng2-dnd) [![npm monthly downloads](https://img.shields.io/npm/dm/ng2-dnd.svg?style=flat-square)](https://www.npmjs.com/package/ng2-dnd)[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) ======================= Angular 2 Drag-and-Drop without dependencies. ## Installation ```bash npm install ng2-dnd --save ``` ## Demo Simple examples using ng2-dnd: - with SystemJS in [ng2-systemjs-demo](https://github.com/akserg/ng2-systemjs-demo) - with Webpack in [ng2-webpack-demo](https://github.com/akserg/ng2-webpack-demo) Online demo available [here](http://akserg.github.io/ng2-webpack-demo) ## Usage If you use SystemJS to load your files, you might have to update your config with this if you don't use `defaultJSExtensions: true`: ```js System.config({ packages: { "/ng2-dnd": {"defaultExtension": "js"} } }); ``` Finally, you can use *ng2-dnd* in your Angular 2 project: - Import `DND_PROVIDERS, DND_DIRECTIVES` from `ng2-dnd/ng2-dnd`; - Use `DND_PROVIDERS` in the bootstrap of your application; - Add `DND_DIRECTIVES` to the `directives` property of your application component; - Use `dnd-draggable` and `dnd-droppable` properties in template of your components. ```js import {Component} from 'angular2/core'; import {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd'; import {bootstrap} from 'angular2/platform/browser'; bootstrap(AppComponent, [ DND_PROVIDERS // It is required to have 1 unique instance of your service ]); @Component({ selector: 'app', directives: [DND_DIRECTIVES], template: ` <h4>Simple Drag-and-Drop</h4> <div class="row"> <div class="col-sm-3"> <div class="panel panel-success"> <div class="panel-heading">Available to drag</div> <div class="panel-body"> <div class="panel panel-default" dnd-draggable [dragEnabled]="true"> <div class="panel-body"> <div>Drag Me</div> </div> </div> </div> </div> </div> <div class="col-sm-3"> <div dnd-droppable class="panel panel-info"> <div class="panel-heading">Place to drop</div> <div class="panel-body"> </div> </div> </div> <div class="col-sm-3"> <div dnd-droppable class="panel panel-warning"> <div class="panel-heading">Restricted to drop</div> <div class="panel-body"> </div> </div> </div> </div> ` }) export class AppComponent { constructor() { } } ``` # Restriction Drag-and-Drop operations with drop zones You can use property *dropZones* (actually an array) to specify in which place you would like to drop the draggable element: ```js import {Component} from 'angular2/core'; import {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd'; import {bootstrap} from 'angular2/platform/browser'; bootstrap(AppComponent, [ DND_PROVIDERS // It is required to have 1 unique instance of your service ]); @Component({ selector: 'app', directives: [DND_DIRECTIVES], template: ` <h4>Restricting Drag-and-Drop with zones</h4> <div class="row"> <div class="col-sm-3"> <div class="panel panel-primary"> <div class="panel-heading">Available to drag</div> <div class="panel-body"> <div class="panel panel-default" dnd-draggable [dragEnabled]="true" [dropZones]="['zone1']"> <div class="panel-body"> <div>Drag Me</div> <div>Zone 1 only</div> </div> </div> </div> </div> <div class="panel panel-success"> <div class="panel-heading">Available to drag</div> <div class="panel-body"> <div class="panel panel-default" dnd-draggable [dragEnabled]="true" [dropZones]="['zone1', 'zone2']"> <div class="panel-body"> <div>Drag Me</div> <div>Zone 1 & 2</div> </div> </div> </div> </div> </div> <div class="col-sm-3"> <div dnd-droppable class="panel panel-info" [dropZones]="['zone1']"> <div class="panel-heading">Zone 1</div> <div class="panel-body"> </div> </div> </div> <div class="col-sm-3"> <div dnd-droppable class="panel panel-warning" [dropZones]="['zone2']"> <div class="panel-heading">Zone 2</div> <div class="panel-body"> </div> </div> </div> </div> ` }) export class AppComponent { constructor() { } } ``` # Transfer custom data via Drag-and-Drop You can transfer data from draggable to droppable component via *dragData* property of Draggable component: ```js import {Component} from 'angular2/core'; import {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd'; import {bootstrap} from 'angular2/platform/browser'; bootstrap(AppComponent, [ DND_PROVIDERS // It is required to have 1 unique instance of your service ]); @Component({ selector: 'app', directives: [DND_DIRECTIVES], template: ` <h4>Transfer custom data in Drag-and-Drop</h4> <div class="row"> <div class="col-sm-3"> <div class="panel panel-success"> <div class="panel-heading">Available to drag</div> <div class="panel-body"> <div class="panel panel-default" dnd-draggable [dragEnabled]="true" [dragData]="transferData"> <div class="panel-body"> <div>Drag Me</div> <div>{{transferData | json}}</div> </div> </div> </div> </div> </div> <div class="col-sm-3"> <div dnd-droppable class="panel panel-info" (onDropSuccess)="transferDataSuccess($event)"> <div class="panel-heading">Place to drop (Items:{{receivedData.length}})</div> <div class="panel-body"> <div [hidden]="!receivedData.length > 0" *ngFor="#data of receivedData">{{data | json}}</div> </div> </div> </div> </div> ` }) export class AppComponent { transferData:Object = {id:1, msg: 'Hello'}; receivedData:Array<any> = []; constructor() { } transferDataSuccess($event) { this.receivedData.push($event); } } ``` # Complex example (includes all shown above) with Drag-and-Drop Here is an example of shopping backet with products adding via drag and drop operation: ```js import {Component} from 'angular2/core'; import {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd'; import {bootstrap} from 'angular2/platform/browser'; bootstrap(AppComponent, [ DND_PROVIDERS // It is required to have 1 unique instance of your service ]); @Component({ selector: 'app', directives: [DND_DIRECTIVES], template: ` <h4>Shopping basket</h4> <div class="row"> <div class="col-sm-3"> <div class="panel panel-success"> <div class="panel-heading">Available products</div> <div class="panel-body"> <div *ngFor="#product of availableProducts" class="panel panel-default" dnd-draggable [dragEnabled]="product.quantity>0" [dragData]="product" (onDragSuccess)="orderedProduct($event)" [dropZones]="['demo1']"> <div class="panel-body"> <div [hidden]="product.quantity===0">{{product.name}} - \${{product.cost}} <br>(available: {{product.quantity}})</div> <div [hidden]="product.quantity>0"><del>{{product.name}}</del> <br>(NOT available)</div> </div> </div> </div> </div> </div> <div class="col-sm-3"> <div dnd-droppable (onDropSuccess)="addToBasket($event)" [dropZones]="['demo1']" class="panel panel-info"> <div class="panel-heading">Shopping Basket<br>(to pay: \${{totalCost()}})</div> <div class="panel-body"> <div *ngFor="#product of shoppingBasket" class="panel panel-default"> <div class="panel-body"> {{product.name}}<br>(ordered: {{product.quantity}} <br>cost: \${{product.cost * product.quantity}}) </div> </div> </div> </div> </div> </div> ` }) export class AppComponent { availableProducts: Array<Product> = []; shoppingBasket: Array<Product> = []; constructor() { this.availableProducts.push(new Product("Blue Shoes", 3, 35)); this.availableProducts.push(new Product("Good Jacket", 1, 90)); this.availableProducts.push(new Product("Red Shirt", 5, 12)); this.availableProducts.push(new Product("Blue Jeans", 4, 60)); } orderedProduct(orderedProduct: Product) { orderedProduct.quantity--; } addToBasket(newProduct: Product) { for (let indx in this.shoppingBasket) { let product:Product = this.shoppingBasket[indx]; if (product.name === newProduct.name) { product.quantity++; return; } } this.shoppingBasket.push(new Product(newProduct.name, 1, newProduct.cost)); } totalCost():number { let cost:number = 0; for (let indx in this.shoppingBasket) { let product:Product = this.shoppingBasket[indx]; cost += (product.cost * product.quantity); } return cost; } } ``` # Simple sortable with Drag-and-Drop Here is an example of simple sortable of favorite drinks moving in container via drag and drop operation: ```js import {Component} from 'angular2/core'; import {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd'; import {bootstrap} from 'angular2/platform/browser'; bootstrap(AppComponent, [ DND_PROVIDERS // It is required to have 1 unique instance of your service ]); @Component({ selector: 'app', directives: [DND_DIRECTIVES], template: ` <h4>Simple sortable</h4> <div class="row"> <div class="col-sm-3"> <div class="panel panel-success"> <div class="panel-heading"> Favorite drinks </div> <div class="panel-body"> <ul class="list-group" dnd-sortable-container [sortableData]="listOne"> <li *ngFor="#item of listOne; #i = index" class="list-group-item" dnd-sortable [sortableIndex]="i">{{item}}</li> </ul> </div> </div> </div> <div class="col-sm-6"> <div class="panel panel-default"> <div class="panel-body"> My prefences:<br/> <span *ngFor="#item of listOne; #i = index">{{i + 1}}) {{item}}<br/></span> </div> </div> </div> </div>` }) export class AppComponent { listOne:Array<string> = ['Coffee','Orange Juice','Red Wine','Unhealty drink!','Water']; } ``` # Multi list sortable with Drag-and-Drop Here is an example of multi list sortable of boxers moving in container and between containers via drag and drop operation: ```js import {Component} from 'angular2/core'; import {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd'; import {bootstrap} from 'angular2/platform/browser'; bootstrap(AppComponent, [ DND_PROVIDERS // It is required to have 1 unique instance of your service ]); @Component({ selector: 'app', directives: [DND_DIRECTIVES], template: ` <h4>Multi list sortable</h4> <div class="row"> <div class="col-sm-3"> <div class="panel panel-warning"> <div class="panel-heading"> Available boxers </div> <div class="panel-body" dnd-sortable-container [dropZones]="['boxers-zone']" [sortableData]="listBoxers"> <ul class="list-group" > <li *ngFor="#item of listBoxers; #i = index" class="list-group-item" dnd-sortable [sortableIndex]="i">{{item}}</li> </ul> </div> </div> </div> <div class="col-sm-3"> <div class="panel panel-success"> <div class="panel-heading"> First Team </div> <div class="panel-body" dnd-sortable-container [dropZones]="['boxers-zone']" [sortableData]="listTeamOne"> <ul class="list-group" > <li *ngFor="#item of listTeamOne; #i = index" class="list-group-item" dnd-sortable [sortableIndex]="i">{{item}}</li> </ul> </div> </div> </div> <div class="col-sm-3"> <div class="panel panel-info"> <div class="panel-heading"> Second Team </div> <div class="panel-body" dnd-sortable-container [dropZones]="['boxers-zone']" [sortableData]="listTeamTwo"> <ul class="list-group"> <li *ngFor="#item of listTeamTwo; #i = index" class="list-group-item" dnd-sortable [sortableIndex]="i">{{item}}</li> </ul> </div> </div> </div> </div>` }) export class AppComponent { listBoxers:Array<string> = ['Sugar Ray Robinson','Muhammad Ali','George Foreman','Joe Frazier','Jake LaMotta','Joe Louis','Jack Dempsey','Rocky Marciano','Mike Tyson','Oscar De La Hoya']; listTeamOne:Array<string> = []; listTeamTwo:Array<string> = []; } ``` # Credits - [Sergey Akopkokhyants](https://github.com/akserg) - [Francesco Cina](https://github.com/ufoscout) # License [MIT](/LICENSE)