<!DOCTYPE html>
<html>
<head>
<script>document.write('<base href="' + document.location + '" />');</script>
<script type="text/javascript" charset="utf-8">
window.AngularVersionForThisPlunker = 'latest'
</script>
<title>angular4-drag-drop demo</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" >
<!-- Polyfills -->
<script src="https://unpkg.com/core-js/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js@0.7.4?main=browser"></script>
<script src="https://unpkg.com/systemjs@0.19.39/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<app-root>Loading AppComponent content here ...</app-root>
</body>
</html>
/* Styles go here */
### Angular4 Drag Demo
Demo using the angular4-drag-drop
https://www.npmjs.com/package/angular4-drag-drop
/**
* WEB ANGULAR VERSION
* (based on systemjs.config.js in angular.io)
* System configuration for Angular samples
* Adjust as necessary for your application needs.
*/
(function (global) {
System.config({
// DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
transpiler: 'ts',
typescriptOptions: {
// Copy of compiler options in standard tsconfig.json
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": ["es2015", "dom"],
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true
},
meta: {
'typescript': {
"exports": "ts"
}
},
paths: {
// paths serve as alias
'npm:': 'https://unpkg.com/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
'app': 'app',
// angular bundles
'@angular/animations': 'npm:@angular/animations/bundles/animations.umd.js',
'@angular/animations/browser': 'npm:@angular/animations/bundles/animations-browser.umd.js',
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser/animations': 'npm:@angular/platform-browser/bundles/platform-browser-animations.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
'@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
'@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
// other libraries
'rxjs': 'npm:rxjs@5.0.1',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
'ts': 'npm:plugin-typescript@5.2.7/lib/plugin.js',
'typescript': 'npm:typescript@2.3.2/lib/typescript.js',
'angular4-drag-drop': 'https://unpkg.com/angular4-drag-drop@1.0.0'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts',
meta: {
'./*.ts': {
loader: 'systemjs-angular-loader.js'
}
}
},
rxjs: {
defaultExtension: 'js'
},
'angular4-drag-drop': {
main: 'angular4-drag-drop.js',
defaultExtension: 'js'
}
}
});
})(this);
//main entry point
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app';
platformBrowserDynamic().bootstrapModule(AppModule)
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { DragDropDirectiveModule} from "angular4-drag-drop";
import { AppComponent } from './app.component';
import { DropAreaComponent } from './drop-area/drop-area.component';
import { NavigationComponent } from './navigation/navigation.component';
import { GenericBoxModule } from './generic-box/generic-box.module';
import { TypeCheckModule } from './type-check/type-check.module';
@NgModule({
imports: [
BrowserModule,
GenericBoxModule,
DragDropDirectiveModule,
TypeCheckModule
],
declarations: [
AppComponent,
DropAreaComponent,
NavigationComponent
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-navigation',
template:`
<div *ngFor="let item of itemsToDrop" [dragDirective]='item' [dragHightlight]="'highlight'" (releaseDrop)="releaseDrop($event)" class="dragItem" >
<app-generic-box [genericBox]='item'></app-generic-box>
</div>
`,
styleUrls: ['./navigation.component.css']
})
export class NavigationComponent implements OnInit {
private itemsToDrop:Array<Object> = [
{
name: 'Item to drop 1',
content: 'desctiption 1'
},
{
name: 'Item to drop 2',
content: 'desctiption 2'
},
{
name: 'Item to drop 3',
content: 'desctiption 3'
},
]
constructor() { }
ngOnInit() {
}
private releaseDrop(event){
let index = this.itemsToDrop.indexOf(event);
if (index >= 0){
this.itemsToDrop.splice(index,1);
}
}
}
import { Component} from '@angular/core';
@Component({
selector: 'app-drop-area',
template:`
<p>
drop-area works!
</p>
<div dropDirective (dropEvent)="addDropItem($event)" class="droppable" [dropHighlight]="'highlight'" >
<app-generic-box *ngFor="let item of itemsDropped" [genericBox]='item' class="dropItem"></app-generic-box>
</div>
`,
styleUrls: ['./drop-area.component.css']
})
export class DropAreaComponent{
private itemsDropped:Array<any> = [];
constructor() { }
private addDropItem(event){
this.itemsDropped.push(event);
}
}
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { GenericBoxComponent } from './generic-box.component';
@NgModule({
imports: [
CommonModule
],
declarations: [
GenericBoxComponent
],
exports: [GenericBoxComponent]
})
export class GenericBoxModule { }
import { Component, OnInit,Input } from '@angular/core';
@Component({
selector: 'app-generic-box',
template: `
<div class="genericBox">
{{genericBox.name}}
<p>{{genericBox.content}}</p>
</div>
`
})
export class GenericBoxComponent implements OnInit {
@Input()
genericBox:Object;
constructor() { }
ngOnInit() {
if (!this.genericBox){
this.genericBox = {name:'Generic Box 1', content:'Generic Box 1 Content'}
}
}
}
var templateUrlRegex = /templateUrl\s*:(\s*['"`](.*?)['"`]\s*)/gm;
var stylesRegex = /styleUrls *:(\s*\[[^\]]*?\])/g;
var stringRegex = /(['`"])((?:[^\\]\\\1|.)*?)\1/g;
module.exports.translate = function(load){
if (load.source.indexOf('moduleId') != -1) return load;
var url = document.createElement('a');
url.href = load.address;
var basePathParts = url.pathname.split('/');
basePathParts.pop();
var basePath = basePathParts.join('/');
var baseHref = document.createElement('a');
baseHref.href = this.baseURL;
baseHref = baseHref.pathname;
if (!baseHref.startsWith('/base/')) { // it is not karma
basePath = basePath.replace(baseHref, '');
}
load.source = load.source
.replace(templateUrlRegex, function(match, quote, url){
var resolvedUrl = url;
if (url.startsWith('.')) {
resolvedUrl = basePath + url.substr(1);
}
return 'templateUrl: "' + resolvedUrl + '"';
})
.replace(stylesRegex, function(match, relativeUrls) {
var urls = [];
while ((match = stringRegex.exec(relativeUrls)) !== null) {
if (match[2].startsWith('.')) {
urls.push('"' + basePath + match[2].substr(1) + '"');
} else {
urls.push('"' + match[2] + '"');
}
}
return "styleUrls: [" + urls.join(', ') + "]";
});
return load;
};
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<div class="col-xs-12">
<div class="row">
<h1>
{{title}}
</h1>
</div>
<div class="row">
<h2>Very Basic</h2>
<div class="col-md-4">
<h3>Box from which to drag</h3>
<app-navigation></app-navigation>
</div>
<div class="col-md-8">
<h3>Box to drag things into</h3>
<app-drop-area></app-drop-area>
</div>
</div>
<app-type-check></app-type-check>
</div>
`
,
styles: ['.main{padding:10px;}']
})
export class AppComponent {
title = 'Draggable Boxes for Angular';
}
.dragItem{
border:1px solid #aaa;
width:50%;
padding:2px 4px;
margin:5px 0;
}
.highlight{
border:solid 1px #0d0;
}
.droppable{
padding:10px;
border:1px solid #bbb;
min-height:60px;
}
.highlight{
border:solid 1px #0d0;
}
.dropItem{
display:inline-block;
padding:2px 4px;
margin:4px;
border:1px solid #aaa;
background-color:#aaf;
}
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { GenericBoxModule } from '../generic-box/generic-box.module';
import { DragDropDirectiveModule} from "angular4-drag-drop";
import { TypeCheckComponent } from './type-check.component';
import { DropAreaTypeCheckComponent} from './drop-area-type-check/drop-area-type-check.component';
import { NavigationTypeCheckComponent } from './navigation-type-check/navigation-type-check.component';
@NgModule({
imports: [
CommonModule,
GenericBoxModule,
DragDropDirectiveModule
],
declarations: [
DropAreaTypeCheckComponent,
NavigationTypeCheckComponent,
TypeCheckComponent
],
exports: [TypeCheckComponent]
})
export class TypeCheckModule { }
import { Component } from '@angular/core';
import { TypeCheckEnum } from './type-check-enum';
@Component({
selector: 'app-type-check',
template: `
<div class="row">
<h2>{{Title}}</h2>
<div class="col-md-4">
<app-navigation-type-check [dropItemType]='dropItemType'></app-navigation-type-check>
</div>
<div class="col-md-8">
<app-drop-area-type-check (droppedItemType)="dropItemTypeCheck($event)"></app-drop-area-type-check>
</div>
</div>
`
})
export class TypeCheckComponent {
private title:String = 'Draggable Items that check to see if they are allowed to drop in drop areas';
private dropItemType:any;
private dropItemTypeCheck(event){
this.dropItemType = event;
}
}
export class EmptyEnumClass{}
export enum TypeCheckEnum{
Round,
Square
}
import { Component, Output, EventEmitter } from '@angular/core';
import {EmptyEnumClass, TypeCheckEnum} from '../type-check-enum';
@Component({
selector: 'app-drop-area-type-check',
template: `
<p>
Match Shapes<br />
{{warningMessage}}
</p>
<div dropDirective (dropEvent)="addDropItem($event,typeCheck.Round)" (dragenterEvent)="dragEnter($event,typeCheck.Round)" (dragleaveEvent)="dragLeave()" class="droppable round-hole" [ngClass]="highlight[typeCheck.Round]">
<app-generic-box *ngFor="let item of itemsDroppedRound" [genericBox]='item'></app-generic-box>
</div>
<div dropDirective (dropEvent)="addDropItem($event,typeCheck.Square)" (dragenterEvent)="dragEnter($event,typeCheck.Square)" (dragleaveEvent)="dragLeave()" class="droppable square-hole" [ngClass]="highlight[typeCheck.Square]" >
<app-generic-box *ngFor="let item of itemsDroppedSquare" [genericBox]='item'></app-generic-box>
</div>
`,
styleUrls: ['./drop-area-type-check.component.css']
})
export class DropAreaTypeCheckComponent{
private itemsDroppedRound:Array<any> = [];
private itemsDroppedSquare:Array<any> = [];
private warningMessage:string = '';
private highlight:Array<string> = ['',''];
private typeCheck = TypeCheckEnum;
@Output()
droppedItemType:EventEmitter<any> = new EventEmitter();
constructor() { }
private addDropItem(event,type){
if (type === TypeCheckEnum.Square){
if (event.type === TypeCheckEnum.Square){
this.itemsDroppedSquare.push(event);
this.droppedItemType.emit(event.type);
this.warningMessage = '';
}else{
this.warningMessage = "Technically a round shape will fit in a square shape, try to match them"
}
}
if (type === TypeCheckEnum.Round){
if (event.type === TypeCheckEnum.Round){
this.itemsDroppedRound.push(event);
this.droppedItemType.emit(event.type);
this.warningMessage = '';
}else {
this.warningMessage ="A square shape will not fit in a round shape."
}
}
}
private dragEnter(event,type){
if (event.type !== type){
this.highlight[type] = 'badHighlight';
} else {
this.highlight[type] = 'highlight';
}
}
private dragLeave(){
this.highlight=['',''];
}
}
.droppable{
padding:10px;
border:solid 1px #aaa;
height:100px;
width:100px;
display:inline-block;
margin:0 10px;
}
.highlight{
border:solid 1px #0f0;
}
.badHighlight{
border:solid 1px #f00;
}
.round-hole{
border-radius:50px;
}
import { Component, OnInit, Input } from '@angular/core';
import {EmptyEnumClass, TypeCheckEnum} from '../type-check-enum';
@Component({
selector: 'app-navigation-type-check',
template: `
navigation works!
<div *ngFor="let item of itemsToDrop" [dragDirective]='item' [dragHightlight]="'highlight'" (releaseDrop)="releaseDrop($event)" class="dragItem" [ngClass]="{'dragItem-round':item.type===0,'dragItem-square':item.type===1}" (startDrag)="startDrag(item)">
<app-generic-box [genericBox]='item'></app-generic-box>
</div>
`,
styleUrls: ['./navigation-type-check.component.css']
})
export class NavigationTypeCheckComponent {
@Input()
dropItemType:any;
private pegType = TypeCheckEnum;
private itemsToDrop:Array<Object> = [
{
name: 'Round Peg ',
content: 'description 1',
type: TypeCheckEnum.Round
},
{
name: 'Square Peg',
content: 'description 2',
type: TypeCheckEnum.Square
},
]
constructor() { }
private releaseDrop(event){
let index = this.itemsToDrop.indexOf(event);
if (index >= 0){
setTimeout(() => {(this.checkType(event,index),100)});
}
}
private checkType(event,index){
if (event.type===this.dropItemType){
this.itemsToDrop.splice(index,1);
}
}
private startDrag(item){
console.log('Begining to drag item: ' + item);
}
}
.dragItem{
border:1px solid #aaa;
padding:2px 4px;
margin:5px 0;
width:90px;
height:90px;
}
.dragItem-round{
border-radius:45px;
}
.highlight{
border:solid 1px #0d0;
}