UNPKG

29 kBMarkdownView Raw
1# Angular 2 Drag-and-Drop [![npm version](https://badge.fury.io/js/ng2-dnd.svg)](https://badge.fury.io/js/ng2-dnd) [![npm monthly downloads](https://img.shields.io/npm/dm/ng2-dnd.svg?style=flat-square)](https://www.npmjs.com/package/ng2-dnd)
2Angular 2 Drag-and-Drop without dependencies.
3
4Follow me [![twitter](https://img.shields.io/twitter/follow/akopkokhyants.svg?style=social&label=%20akopkokhyants)](https://twitter.com/akopkokhyants) to be notified about new releases.
5
6[![Build Status](https://travis-ci.org/akserg/ng2-dnd.svg?branch=master)](https://travis-ci.org/akserg/ng2-dnd)
7[![Dependency Status](https://david-dm.org/akserg/ng2-dnd.svg)](https://david-dm.org/akserg/ng2-dnd)
8[![devDependency Status](https://david-dm.org/akserg/ng2-dnd/dev-status.svg)](https://david-dm.org/akserg/ng2-dnd#info=devDependencies)
9[![Known Vulnerabilities](https://snyk.io/test/github/akserg/ng2-dnd/badge.svg)](https://snyk.io/test/github/akserg/ng2-dnd)
10
11_Some of these APIs and Components are not final and are subject to change!_
12
13## Transpilation to Angular Package Format
14The library uses [ng-packagr](https://github.com/dherges/ng-packagr) to transpile into the Angular Package Format:
15- Bundles library in `FESM2015`, `FESM5`, and `UMD` formats
16- The npm package can be consumed by `Angular CLI`, `Webpack`, or `SystemJS`
17- Creates type definitions (`.d.ts`)
18- Generates Ahead-of-Time metadata (`.metadata.json`)
19- Auto-discovers and bundles secondary entry points such as `@my/foo`, `@my/foo/testing`, `@my/foo/bar`
20
21## Installation
22```bash
23npm install ng2-dnd --save
24```
25
26## Demo
27- Webpack demo available [here](https://angular-dxqjhj.stackblitz.io)
28- SystemJS demo available [here](http://embed.plnkr.co/JbG8Si)
29
30## Usage
31If you use SystemJS to load your files, you might have to update your config:
32
33```js
34System.config({
35 map: {
36 'ng2-dnd': 'node_modules/ng2-dnd/bundles/ng2-dnd.umd.js'
37 }
38});
39```
40
41#### 1. Add the default styles
42- Import the `style.css` into your web page from `node_modules/ng2-dnd/bundles/style.css`
43
44#### 2. Import the `DndModule`
45Import `DndModule.forRoot()` in the NgModule of your application.
46The `forRoot` method is a convention for modules that provide a singleton service.
47
48```ts
49import {BrowserModule} from "@angular/platform-browser";
50import {NgModule} from '@angular/core';
51import {DndModule} from 'ng2-dnd';
52
53@NgModule({
54 imports: [
55 BrowserModule,
56 DndModule.forRoot()
57 ],
58 bootstrap: [AppComponent]
59})
60export class AppModule {
61}
62```
63
64If you have multiple NgModules and you use one as a shared NgModule (that you import in all of your other NgModules),
65don't forget that you can use it to export the `DndModule` that you imported in order to avoid having to import it multiple times.
66
67```ts
68@NgModule({
69 imports: [
70 BrowserModule,
71 DndModule
72 ],
73 exports: [BrowserModule, DndModule],
74})
75export class SharedModule {
76}
77```
78
79#### 3. Use Drag-and-Drop operations with no code
80
81```js
82import {Component} from '@angular/core';
83
84@Component({
85 selector: 'simple-dnd',
86 template: `
87<h4>Simple Drag-and-Drop</h4>
88<div class="row">
89 <div class="col-sm-3">
90 <div class="panel panel-success">
91 <div class="panel-heading">Available to drag</div>
92 <div class="panel-body">
93 <div class="panel panel-default" dnd-draggable [dragEnabled]="true">
94 <div class="panel-body">
95 <div>Drag Me</div>
96 </div>
97 </div>
98 </div>
99 </div>
100 </div>
101 <div class="col-sm-3">
102 <div dnd-droppable class="panel panel-info" (onDropSuccess)="simpleDrop=$event">
103 <div class="panel-heading">Place to drop</div>
104 <div class="panel-body">
105 <div *ngIf="simpleDrop">Item was dropped here</div>
106 </div>
107 </div>
108 </div>
109</div>`
110})
111export class SimpleDndComponent {
112 simpleDrop: any = null;
113}
114```
115
116#### 4. Add handle to restrict draggable zone of component
117
118```js
119import {Component} from '@angular/core';
120
121@Component({
122 selector: 'simple-dnd-handle',
123 template: `
124<h4>Simple Drag-and-Drop with handle</h4>
125<div class="row">
126 <div class="col-sm-3">
127 <div class="panel panel-success">
128 <div class="panel-heading">Available to drag</div>
129 <div class="panel-body">
130 <div class="panel panel-default" dnd-draggable [dragEnabled]="true">
131 <div class="panel-body">
132 <div>
133 <span dnd-draggable-handle>=</span>&nbsp;
134 Drag Handle
135 </div>
136 </div>
137 </div>
138 </div>
139 </div>
140 </div>
141 <div class="col-sm-3">
142 <div dnd-droppable class="panel panel-info" (onDropSuccess)="simpleDrop=$event">
143 <div class="panel-heading">Place to drop</div>
144 <div class="panel-body">
145 <div *ngIf="simpleDrop">Item was dropped here</div>
146 </div>
147 </div>
148 </div>
149</div>`
150})
151export class SimpleDndHandleComponent {
152 simpleDrop: any = null;
153}
154```
155
156#### 5. Restriction Drag-and-Drop operations with drop zones
157You can use property *dropZones* (actually an array) to specify in which place you would like to drop the draggable element:
158
159```js
160import {Component} from '@angular/core';
161
162@Component({
163 selector: 'zone-dnd',
164 template: `
165<h4>Restricted Drag-and-Drop with zones</h4>
166<div class="row">
167 <div class="col-sm-3">
168 <div class="panel panel-primary">
169 <div class="panel-heading">Available to drag</div>
170 <div class="panel-body">
171 <div class="panel panel-default" dnd-draggable [dragEnabled]="true" [dropZones]="['zone1']">
172 <div class="panel-body">
173 <div>Drag Me</div>
174 <div>Zone 1 only</div>
175 </div>
176 </div>
177 </div>
178 </div>
179
180 <div class="panel panel-success">
181 <div class="panel-heading">Available to drag</div>
182 <div class="panel-body">
183 <div class="panel panel-default" dnd-draggable [dragEnabled]="true" [dropZones]="['zone1', 'zone2']">
184 <div class="panel-body">
185 <div>Drag Me</div>
186 <div>Zone 1 & 2</div>
187 </div>
188 </div>
189 </div>
190 </div>
191 </div>
192 <div class="col-sm-3">
193 <div dnd-droppable class="panel panel-info" [dropZones]="['zone1']" (onDropSuccess)="restrictedDrop1=$event">
194 <div class="panel-heading">Zone 1</div>
195 <div class="panel-body">
196 <div *ngIf="restrictedDrop1">Item was dropped here</div>
197 </div>
198 </div>
199 </div>
200 <div class="col-sm-3">
201 <div dnd-droppable class="panel panel-warning" [dropZones]="['zone2']" (onDropSuccess)="restrictedDrop2=$event">
202 <div class="panel-heading">Zone 2</div>
203 <div class="panel-body">
204 <div *ngIf="restrictedDrop2">Item was dropped here</div>
205 </div>
206 </div>
207 </div>
208</div>`
209})
210export class ZoneDndComponent {
211 restrictedDrop1: any = null;
212 restrictedDrop2: any = null;
213}
214```
215
216#### 6. Transfer custom data via Drag-and-Drop
217You can transfer data from draggable to droppable component via *dragData* property of Draggable component:
218
219```js
220import {Component} from '@angular/core';
221
222@Component({
223 selector: 'custom-data-dnd',
224 template: `
225<h4>Transfer custom data in Drag-and-Drop</h4>
226<div class="row">
227 <div class="col-sm-3">
228 <div class="panel panel-success">
229 <div class="panel-heading">Available to drag</div>
230 <div class="panel-body">
231 <div class="panel panel-default" dnd-draggable [dragEnabled]="true" [dragData]="transferData">
232 <div class="panel-body">
233 <div>Drag Me</div>
234 <div>{{transferData | json}}</div>
235 </div>
236 </div>
237 </div>
238 </div>
239 </div>
240 <div class="col-sm-3">
241 <div dnd-droppable class="panel panel-info" (onDropSuccess)="transferDataSuccess($event)">
242 <div class="panel-heading">Place to drop (Items:{{receivedData.length}})</div>
243 <div class="panel-body">
244 <div [hidden]="!receivedData.length > 0" *ngFor="let data of receivedData">{{data | json}}</div>
245 </div>
246 </div>
247 </div>
248</div>`
249})
250export class CustomDataDndComponent {
251 transferData: Object = {id: 1, msg: 'Hello'};
252 receivedData: Array<any> = [];
253
254 transferDataSuccess($event: any) {
255 this.receivedData.push($event);
256 }
257}
258```
259
260#### 7. Use a custom function to determine where dropping is allowed
261For use-cases when a static set of `dropZone`s is not possible, a custom function can be used to dynamically determine whether an item can be dropped or not. To achieve that, set the `allowDrop` property to this boolean function.
262
263In the following example, we have two containers that only accept numbers that are multiples of a user-input base integer. `dropZone`s are not helpful here because they are static, whereas the user input is dynamic.
264
265```js
266import { Component } from '@angular/core';
267
268@Component({
269 selector: 'custom-function-dnd',
270 template: `
271<h4>Use a custom function to determine where dropping is allowed</h4>
272<div class="row">
273 <div class="col-sm-3">
274 <div class="panel panel-success">
275 <div class="panel-heading">Available to drag</div>
276 <div class="panel-body">
277 <div class="panel panel-default" dnd-draggable [dragData]="6">
278 <div class="panel-body">dragData = 6</div>
279 </div>
280 <div class="panel panel-default" dnd-draggable [dragData]="10">
281 <div class="panel-body">dragData = 10</div>
282 </div>
283 <div class="panel panel-default" dnd-draggable [dragData]="30">
284 <div class="panel-body">dragData = 30</div>
285 </div>
286 </div>
287 </div>
288 </div>
289 <div class="col-sm-6">
290 <pre>allowDropFunction(baseInteger: any): any {{ '{' }}
291 return (dragData: any) => dragData % baseInteger === 0;
292{{ '}' }}</pre>
293 <div class="row">
294 <div class="col-sm-6">
295 <div dnd-droppable class="panel panel-info" [allowDrop]="allowDropFunction(box1Integer)" (onDropSuccess)="addTobox1Items($event)">
296 <div class="panel-heading">
297 Multiples of
298 <input type="number" [(ngModel)]="box1Integer" style="width: 4em">
299 only
300 </div>
301 <div class="panel-body">
302 <div *ngFor="let item of box1Items">dragData = {{item}}</div>
303 </div>
304 </div>
305 </div>
306 <div class="col-sm-6">
307 <div dnd-droppable class="panel panel-warning" [allowDrop]="allowDropFunction(box2Integer)" (onDropSuccess)="addTobox2Items($event)">
308 <div class="panel-heading">
309 Multiples of
310 <input type="number" [(ngModel)]="box2Integer" style="width: 4em">
311 only
312 </div>
313 <div class="panel-body">
314 <div *ngFor="let item of box2Items">dragData = {{item}}</div>
315 </div>
316 </div>
317 </div>
318 </div>
319 </div>
320</div>
321`
322})
323export class CustomFunctionDndComponent {
324 box1Integer: number = 3;
325 box2Integer: number = 10;
326
327 box1Items: string[] = [];
328 box2Items: string[] = [];
329
330 allowDropFunction(baseInteger: number): any {
331 return (dragData: any) => dragData % baseInteger === 0;
332 }
333
334 addTobox1Items($event: any) {
335 this.box1Items.push($event.dragData);
336 }
337
338 addTobox2Items($event: any) {
339 this.box2Items.push($event.dragData);
340 }
341}
342```
343
344#### 8. Shopping basket with Drag-and-Drop
345Here is an example of shopping backet with products adding via drag and drop operation:
346
347```js
348import { Component } from '@angular/core';
349
350@Component({
351 selector: 'shoping-basket-dnd',
352 template: `
353<h4>Drag-and-Drop - Shopping basket</h4>
354<div class="row">
355
356 <div class="col-sm-3">
357 <div class="panel panel-success">
358 <div class="panel-heading">Available products</div>
359 <div class="panel-body">
360 <div *ngFor="let product of availableProducts" class="panel panel-default"
361 dnd-draggable [dragEnabled]="product.quantity>0" [dragData]="product" (onDragSuccess)="orderedProduct($event)" [dropZones]="['demo1']">
362 <div class="panel-body">
363 <div [hidden]="product.quantity===0">{{product.name}} - \${{product.cost}}<br>(available: {{product.quantity}})</div>
364 <div [hidden]="product.quantity>0"><del>{{product.name}}</del><br>(NOT available)</div>
365 </div>
366 </div>
367 </div>
368 </div>
369 </div>
370 <div class="col-sm-3">
371 <div dnd-droppable (onDropSuccess)="addToBasket($event)" [dropZones]="['demo1']" class="panel panel-info">
372 <div class="panel-heading">Shopping Basket<br>(to pay: \${{totalCost()}})</div>
373 <div class="panel-body">
374 <div *ngFor="let product of shoppingBasket" class="panel panel-default">
375 <div class="panel-body">
376 {{product.name}}<br>(ordered: {{product.quantity}}<br>cost: \${{product.cost * product.quantity}})
377 </div>
378 </div>
379 </div>
380 </div>
381 </div>
382</div>`
383})
384export class ShoppingBasketDndComponent {
385 availableProducts: Array<Product> = [];
386 shoppingBasket: Array<Product> = [];
387
388 constructor() {
389 this.availableProducts.push(new Product('Blue Shoes', 3, 35));
390 this.availableProducts.push(new Product('Good Jacket', 1, 90));
391 this.availableProducts.push(new Product('Red Shirt', 5, 12));
392 this.availableProducts.push(new Product('Blue Jeans', 4, 60));
393 }
394
395 orderedProduct($event: any) {
396 let orderedProduct: Product = $event.dragData;
397 orderedProduct.quantity--;
398 }
399
400 addToBasket($event: any) {
401 let newProduct: Product = $event.dragData;
402 for (let indx in this.shoppingBasket) {
403 let product: Product = this.shoppingBasket[indx];
404 if (product.name === newProduct.name) {
405 product.quantity++;
406 return;
407 }
408 }
409 this.shoppingBasket.push(new Product(newProduct.name, 1, newProduct.cost));
410 this.shoppingBasket.sort((a: Product, b: Product) => {
411 return a.name.localeCompare(b.name);
412 });
413 }
414
415 totalCost(): number {
416 let cost: number = 0;
417 for (let indx in this.shoppingBasket) {
418 let product: Product = this.shoppingBasket[indx];
419 cost += (product.cost * product.quantity);
420 }
421 return cost;
422 }
423}
424
425class Product {
426 constructor(public name: string, public quantity: number, public cost: number) {}
427}
428```
429
430#### 9. Simple sortable with Drag-and-Drop
431Here is an example of simple sortable of favorite drinks moving in container via drag and drop operation:
432
433```js
434import {Component} from '@angular/core';
435
436@Component({
437 selector: 'simple-sortable',
438 template: `
439<h4>Simple sortable</h4>
440<div class="row">
441 <div class="col-sm-3">
442 <div class="panel panel-success">
443 <div class="panel-heading">
444 Favorite drinks
445 </div>
446 <div class="panel-body">
447 <ul class="list-group" dnd-sortable-container [sortableData]="listOne">
448 <li *ngFor="let item of listOne; let i = index" class="list-group-item" dnd-sortable [sortableIndex]="i">{{item}}</li>
449 </ul>
450 </div>
451 </div>
452 </div>
453 <div class="col-sm-6">
454 <div class="panel panel-default">
455 <div class="panel-body">
456 My prefences:<br/>
457 <span *ngFor="let item of listOne; let i = index">{{i + 1}}) {{item}}<br/></span>
458 </div>
459 </div>
460 </div>
461</div>`
462})
463export class SimpleSortableComponent {
464 listOne: Array<string> = ['Coffee', 'Orange Juice', 'Red Wine', 'Unhealty drink!', 'Water'];
465}
466```
467
468
469#### 10. Simple sortable with Drag-and-Drop handle
470Add handle to restict grip zone of sortable component.
471
472```js
473import {Component} from '@angular/core';
474
475@Component({
476 selector: 'simple-sortable-handle',
477 template: `
478<h4>Simple sortable handle</h4>
479<div class="row">
480 <div class="col-sm-3">
481 <div class="panel panel-success">
482 <div class="panel-heading">
483 Favorite drinks
484 </div>
485 <div class="panel-body">
486 <ul class="list-group" dnd-sortable-container [sortableData]="listOne">
487 <li *ngFor="let item of listOne; let i = index" class="list-group-item" dnd-sortable [sortableIndex]="i">
488 <span dnd-sortable-handle>=</span>&nbsp;
489 {{item}}
490 </li>
491 </ul>
492 </div>
493 </div>
494 </div>
495 <div class="col-sm-6">
496 <div class="panel panel-default">
497 <div class="panel-body">
498 My prefences:<br/>
499 <span *ngFor="let item of listOne; let i = index">{{i + 1}}) {{item}}<br/></span>
500 </div>
501 </div>
502 </div>
503</div>`
504})
505export class SimpleSortableHandleComponent {
506 listOne: Array<string> = ['Coffee', 'Orange Juice', 'Red Wine', 'Unhealty drink!', 'Water'];
507}
508```
509
510#### 11. Simple sortable With Drop into recycle bin
511Here is an example of multi list sortable of boxers moving in container and between containers via drag and drop operation:
512
513```js
514import {Component} from '@angular/core';
515
516@Component({
517 selector: 'recycle-multi-sortable',
518 template: `
519<h4>Simple sortable With Drop into recycle bin</h4>
520<div class="row">
521 <div class="col-sm-3">
522 <div class="panel panel-success">
523 <div class="panel-heading">
524 Favorite drinks
525 </div>
526 <div class="panel-body" dnd-sortable-container [sortableData]="listOne" [dropZones]="['delete-dropZone']">
527 <ul class="list-group">
528 <li *ngFor="let item of listOne; let i = index" class="list-group-item"
529 dnd-sortable [sortableIndex]="i">{{item}}</li>
530 </ul>
531 </div>
532 </div>
533 </div>
534 <div class="col-sm-6">
535 <div class="panel panel-default">
536 <div class="panel-body" dnd-sortable-container [dropZones]="['delete-dropZone']" [sortableData]="listRecycled">
537 Recycle bin: Drag into me to delete it<br/>
538 </div>
539 </div>
540 <div *ngIf="listRecycled.length">
541 <b>Recycled:</b> <span>{{listRecycled.toString()}} </span>
542 </div>
543 </div>
544</div>`
545})
546export class RecycleMultiSortableComponent {
547 listOne: Array<string> = ['Coffee', 'Orange Juice', 'Red Wine', 'Unhealty drink!', 'Water'];
548 listRecycled: Array<string> = [];
549}
550```
551
552#### 12. Simple sortable With Drop into something, without delete it
553Here is an example of simple sortable list of items copying in target container:
554
555```js
556import {Component} from '@angular/core';
557
558@Component({
559 selector: 'simple-sortable-copy',
560 template: `
561<h4>Simple sortable With Drop into something, without delete it</h4>
562<div class="row">
563 <div class="col-sm-3">
564 <div class="panel panel-warning"
565 dnd-sortable-container [sortableData]="sourceList" [dropZones]="['source-dropZone']">
566 <div class="panel-heading">Source List</div>
567 <div class="panel-body">
568 <ul class="list-group">
569 <li *ngFor="let source of sourceList; let x = index" class="list-group-item"
570 dnd-sortable [sortableIndex]="x" [dragEnabled]="true"
571 [dragData]="source">{{source.name}}</li>
572 </ul>
573 </div>
574 </div>
575 </div>
576 <div class="col-sm-6">
577 <div class="panel panel-info">
578 <div class="panel-heading">Target List</div>
579 <div class="panel-body" dnd-droppable (onDropSuccess)="addTo($event)" [dropZones]="['source-dropZone']">
580 <ul class="list-group">
581 <li *ngFor="let target of targetList" class="list-group-item">
582 {{target.name}}
583 </li>
584 </ul>
585 </div>
586 </div>
587 </div>
588</div>`
589})
590export class SimpleSortableCopyComponent {
591
592 sourceList: Widget[] = [
593 new Widget('1'), new Widget('2'),
594 new Widget('3'), new Widget('4'),
595 new Widget('5'), new Widget('6')
596 ];
597
598 targetList: Widget[] = [];
599 addTo($event: any) {
600 this.targetList.push($event.dragData);
601 }
602}
603
604class Widget {
605 constructor(public name: string) {}
606}
607```
608
609#### 13. Multi list sortable between containers
610Here is an example of multi list sortable of boxers moving in container and between containers via drag and drop operation:
611
612```js
613import {Component} from '@angular/core';
614
615@Component({
616 selector: 'embedded-sortable',
617 template: `
618<h4>Move items between multi list sortable containers</h4>
619<div class="row">
620 <div class="col-sm-3">
621 Drag Containers <input type="checkbox" [(ngModel)]="dragOperation"/>
622 <div dnd-sortable-container [sortableData]="containers" [dropZones]="['container-dropZone']">
623 <div class="col-sm3"
624 *ngFor="let container of containers; let i = index"
625 dnd-sortable [sortableIndex]="i" [dragEnabled]="dragOperation">
626 <div class="panel panel-warning"
627 dnd-sortable-container [sortableData]="container.widgets" [dropZones]="['widget-dropZone']">
628 <div class="panel-heading">
629 {{container.id}} - {{container.name}}
630 </div>
631 <div class="panel-body">
632 <ul class="list-group">
633 <li *ngFor="let widget of container.widgets; let x = index" class="list-group-item"
634 dnd-sortable [sortableIndex]="x" [dragEnabled]="!dragOperation"
635 [dragData]="widget">{{widget.name}}</li>
636 </ul>
637 </div>
638 </div>
639 </div>
640 </div>
641 </div>
642 <div class="col-sm-6">
643 <div class="panel panel-info">
644 <div class="panel-heading">Widgets</div>
645 <div class="panel-body" dnd-droppable (onDropSuccess)="addTo($event)" [dropZones]="['widget-dropZone']">
646 <div *ngFor="let widget of widgets" class="panel panel-default">
647 <div class="panel-body">
648 {{widget.name}}
649 </div>
650 </div>
651 </div>
652 </div>
653 </div>
654</div>`
655})
656export class EmbeddedSortableComponent {
657 dragOperation: boolean = false;
658
659 containers: Array<Container> = [
660 new Container(1, 'Container 1', [new Widget('1'), new Widget('2')]),
661 new Container(2, 'Container 2', [new Widget('3'), new Widget('4')]),
662 new Container(3, 'Container 3', [new Widget('5'), new Widget('6')])
663 ];
664
665 widgets: Array<Widget> = [];
666 addTo($event: any) {
667 if ($event) {
668 this.widgets.push($event.dragData);
669 }
670 }
671}
672
673class Container {
674 constructor(public id: number, public name: string, public widgets: Array<Widget>) {}
675}
676
677class Widget {
678 constructor(public name: string) {}
679}
680```
681
682#### 14. Simple FormArray sortable with Drag-and-Drop
683Here is an example of simple sortable of favorite drinks moving in container via drag and drop operation but using FormArray instead of Array:
684
685```js
686import {Component} from '@angular/core';
687import {FormArray, FormControl} from '@angular/forms';
688
689@Component({
690 selector: 'simple-formarray-sortable',
691 template: `
692<h4>Simple FormArray sortable</h4>
693<div class="row">
694 <div class="col-sm-3">
695 <div class="panel panel-success">
696 <div class="panel-heading">
697 Favorite drinks
698 </div>
699 <div class="panel-body">
700 <ul class="list-group" dnd-sortable-container [sortableData]="listOne">
701 <li *ngFor="let item of listOne.controls; let i = index" class="list-group-item" dnd-sortable [sortableIndex]="i"><input type="text" [formControl]="item"></li>
702 </ul>
703 </div>
704 </div>
705 </div>
706 <div class="col-sm-6">
707 <div class="panel panel-default">
708 <div class="panel-body">
709 My prefences:<br/>
710 <span *ngFor="let item of listOne.controls; let i = index">{{i + 1}}) {{item.value}}<br/></span>
711 </div>
712 </div>
713 </div>
714</div>`
715})
716export class SimpleFormArraySortableComponent {
717 listOne: FormArray = new FormArray([
718 new FormControl('Coffee'),
719 new FormControl('Orange Juice'),
720 new FormControl('Red Wine'),
721 new FormControl('Unhealty drink!'),
722 new FormControl('Water')
723 ]);
724}
725```
726
727## How to pass multiple data in dragData while dragging ?
728
7291) As an array:
730
731``` html
732[dragData]="[aComponent,'component-in-bar']"
733```
734
735``` javascript
736loadComponent($event){
737 console.log($event.dragData[0]); // aComponent
738 console.log($event.dragData[1]); // 'component-in-bar' OR 'component-in-designer'
739}
740```
741
7422) As an object:
743
744``` html
745[dragData]="{component: aComponent, location: 'component-in-bar'}"
746```
747
748``` javascript
749loadComponent($event){
750 console.log($event.dragData.component); // aComponent
751 console.log($event.dragData.location); // 'component-in-bar' OR 'component-in-designer'
752}
753```
754
755# Retreiving files in a drop zone
756
757Since it is possible to drag and drop one or more files to a drop zone, you need to handle the incoming files.
758
759```js
760import {Component} from '@angular/core';
761import {Http, Headers} from '@angular/http';
762import {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd';
763import {bootstrap} from '@angular/platform-browser-dynamic';
764
765bootstrap(AppComponent, [
766 DND_PROVIDERS // It is required to have 1 unique instance of your service
767]);
768
769@Component({
770 selector: 'app',
771 directives: [DND_DIRECTIVES],
772 template: `
773<h4>Simple Drag-and-Drop</h4>
774<div class="row">
775
776 <div class="col-sm-3">
777 <div dnd-droppable class="panel panel-info"
778 (onDropSuccess)="transferDataSuccess($event)">>
779 <div class="panel-heading">Place to drop</div>
780 <div class="panel-body">
781 </div>
782 </div>
783 </div>
784</div>
785`
786})
787export class AppComponent {
788
789 constructor(private _http: Http) { }
790
791 /**
792 * The $event is a structure:
793 * {
794 * dragData: any,
795 * mouseEvent: MouseEvent
796 * }
797 */
798 transferDataSuccess($event) {
799 // let attachmentUploadUrl = 'assets/data/offerspec/offerspec.json';
800 // loading the FileList from the dataTransfer
801 let dataTransfer: DataTransfer = $event.mouseEvent.dataTransfer;
802 if (dataTransfer && dataTransfer.files) {
803
804 // needed to support posting binaries and usual form values
805 let headers = new Headers();
806 headers.append('Content-Type', 'multipart/form-data');
807
808 let files: FileList = dataTransfer.files;
809
810 // uploading the files one by one asynchrounusly
811 for (let i = 0; i < files.length; i++) {
812 let file: File = files[i];
813
814 // just for debugging
815 console.log('Name: ' + file.name + '\n Type: ' + file.type + '\n Size: ' + file.size + '\n Date: ' + file.lastModifiedDate);
816
817 // collecting the data to post
818 var data = new FormData();
819 data.append('file', file);
820 data.append('fileName', file.name);
821 data.append('fileSize', file.size);
822 data.append('fileType', file.type);
823 data.append('fileLastMod', file.lastModifiedDate);
824
825 // posting the data
826 this._http
827 .post(attachmentUploadUrl, data, {
828 headers: headers
829 })
830 .toPromise()
831 .catch(reason => {
832 console.log(JSON.stringify(reason));
833 });
834 }
835 }
836 }
837}
838
839# Credits
840- [Francesco Cina](https://github.com/ufoscout)
841- [Valerii Kuznetsov](https://github.com/solival)
842- [Shane Oborn](https://github.com/obosha)
843- [Juergen Gutsch](https://github.com/JuergenGutsch)
844- [Damjan Cilenšek](https://github.com/loudandwicked)
845
846# License
847 [MIT](/LICENSE)
848
\No newline at end of file