Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

docs(cookbook - jquery plugins) - drag and drop example #1341

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions public/docs/_examples/cb-jquery-plugin/e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict';

import { browser, element, by } from 'protractor';

/* tslint:disable:quotemark */
describe('Drag and Drop', function () {

beforeAll(function () {
browser.get('');
});

it('should drag hero to assignment', function () {

let assignment1 = element.all(by.css('.assignment')).get(0);

let hero1 = element.all(by.css('.hero')).get(0);

browser.actions()
.dragAndDrop(hero1 as any as webdriver.WebElement,
assignment1 as any as webdriver.WebElement)
.perform();

let heroAssignment = element.all(by.xpath('//div[text()="Help Granny cross the street"]/following-sibling::ul/li[text()="Mr. Nice"]'));
expect(heroAssignment.count()).toBe(1);

let doneButton = element(by.xpath('//div[@data-hero="Mr. Nice"]/div/button'));

// Remove Mr. Nice
doneButton.click().then(function(){
let remainingHeroes = element.all(by.css('.hero'));
expect(remainingHeroes.count()).toBe(3);
});
});
});
1 change: 1 addition & 0 deletions public/docs/_examples/cb-jquery-plugin/ts/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**/*.js
33 changes: 33 additions & 0 deletions public/docs/_examples/cb-jquery-plugin/ts/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// #docregion
import { Component } from '@angular/core';

@Component({
selector: 'my-app',
template: `
<div id="hero-wrapper">
<h2>Hero Assignments</h2>
<div *ngFor="let assignment of assignments">
<cb-assignment [title]="assignment"></cb-assignment>
</div>
<div class="heroList">
<div *ngFor="let hero of heroes">
<cb-hero (remove)="removeHero($event)" [name]="hero"></cb-hero>
</div>
</div>
</div>
`
})
export class AppComponent {
heroes = ['Mr. Nice',
'Bombasto',
'Celeritas',
'Tornado'];

assignments = ['Help Granny cross the street',
'Rescue village from dragon(s)',
'Rescue princess from tower'];

removeHero(heroToRemove: string): void {
this.heroes = this.heroes.filter(hero => hero !== heroToRemove);
}
}
13 changes: 13 additions & 0 deletions public/docs/_examples/cb-jquery-plugin/ts/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { HeroAssignmentComponent } from './hero-assignment.component';
import { HeroComponent } from './hero.component';

@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent, HeroAssignmentComponent, HeroComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!-- #docregion -->
<div #assignment class="assignment" [ngClass]="{selected: heroDropped}">
<div>{{title}}</div>
<ul>
<li *ngFor="let hero of assignedHeroes">{{hero}}</li>
</ul>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// #docregion
import { Component, Input, AfterViewInit, ViewChild, ElementRef } from '@angular/core';

declare var jQuery: any;

@Component({
selector: 'cb-assignment',
templateUrl: 'app/hero-assignment.component.html'
})
export class HeroAssignmentComponent implements AfterViewInit {
@Input() title: string;
@ViewChild('assignment') assignment: ElementRef;

assignedHeroes: string[] = [];

// #docregion add-plugin
ngAfterViewInit(): void {
jQuery(this.assignment.nativeElement).droppable({drop : (event: any, ui: any) => {
let heroName = ui.draggable.data('hero');
if (this.assignedHeroes.indexOf(heroName) === -1) {
this.assignedHeroes = [...this.assignedHeroes, heroName];
}
}});
}
// #enddocregion add-plugin
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!-- #docregion -->
<div #hero class="hero" [attr.data-hero]="name">
{{name}}
<div><button (click)="done()">Done</button></div>
</div>
25 changes: 25 additions & 0 deletions public/docs/_examples/cb-jquery-plugin/ts/app/hero.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// #docregion
import { Component, Input, Output, AfterViewInit, ViewChild, ElementRef, EventEmitter } from '@angular/core';

// #docregion declare-jquery
declare var jQuery: any;
// #enddocregion declare-jquery
@Component({
selector: 'cb-hero',
templateUrl: 'app/hero.component.html'
})
export class HeroComponent implements AfterViewInit {
@Input() name: string;
@Output() remove = new EventEmitter<string>();
@ViewChild('hero') hero: ElementRef;

// #docregion add-plugin
ngAfterViewInit(): void {
jQuery(this.hero.nativeElement).draggable({revert: 'invalid'});
}
// #enddocregion add-plugin

done(): void {
this.remove.emit(this.name);
}
}
5 changes: 5 additions & 0 deletions public/docs/_examples/cb-jquery-plugin/ts/app/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule);
34 changes: 34 additions & 0 deletions public/docs/_examples/cb-jquery-plugin/ts/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<title>JQuery Plugin</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- #docregion style -->
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="sample.css">
<!-- #enddocregion style -->

<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>

<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>

<!-- #docregion jquery -->
<script src="https://npmcdn.com/jquery@2.2.3"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<!-- #enddocregion jquery -->

<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>

</head>

<body>
<my-app>Loading app...</my-app>
</body>

</html>
9 changes: 9 additions & 0 deletions public/docs/_examples/cb-jquery-plugin/ts/plnkr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"description": "jQuery Plugin",
"files":[
"!**/*.d.ts",
"!**/*.js",
"!**/*.[1].*"
],
"tags":["cookbook"]
}
30 changes: 30 additions & 0 deletions public/docs/_examples/cb-jquery-plugin/ts/sample.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.hero{
background: lightblue;
border: 1px solid black;
width: 100px;
color:black;
height: 50px;
margin-bottom: 20px;
text-align: center;
padding-top: 30px;
}

.assignment{
background: darkblue;
width: 250px;
height: 150px;
color:white;
margin-right: 20px;
text-align: center;
padding-top: 10px;
float: left;
margin-bottom: 30px;
}

.assignment li{
text-align: left;
}

.heroList{
clear:both;
}
4 changes: 4 additions & 0 deletions public/docs/ts/latest/cookbook/_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
"intro": "Translate the app's template text into multiple languages"
},

"jquery-plugin": {
"title": "jQuery Plugin Integration",
"intro": "Integrate with jQuery plugins"
},
"set-document-title": {
"title": "Set the Document Title",
"intro": "Setting the document or window title using the Title service."
Expand Down
104 changes: 104 additions & 0 deletions public/docs/ts/latest/cookbook/jquery-plugin.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
include ../_util-fns

:marked
Using jQuery for direct DOM access is not recommended in Angular projects, but we do see value in supporting integration with third party jQuery plugins.

In this cookbook we show how to integrate `draggable` and `droppable` from jQuery UI to make it easier for our admins to assign new adventures to our brave heroes.

Before a hero can set out on a new quest, one of our admins will give the hero a new assignment by dragging and dropping the hero's name on top of the assignment.
:marked
**See the [live example](/resources/live-examples/cb-jquery-plugin/ts/plnkr.html)**.

<a id="toc"></a>
:marked
## Table of contents

[Add jQuery](#jquery-add)

[Drag](#drag)

[Drop](#drop)

.l-main-section
<a id="jquery-add"></a>
:marked
## Add jQuery

Before we can start we have to add the necessary script references to load the jQuery library and the two plugins, `draggable` and `droppable`, from jQuery UI.

+makeExample('cb-jquery-plugin/ts/index.html', 'jquery', 'index.html (add jquery scripts)')(format=".")

:marked
jQuery declares a global `jQuery` variable, but this variable is not know to TypeScript. In order to reference `jQuery` from TypeScript we have to declare a corresponding TypeScript variable as well.

In this case we don't need to access the jQuery api, so it's unnecessary to add additional typings for jQuery. Instead we will just declare `jQuery` as an `any` variable.

If we don't declare `jQuery`, the TypeScript compiler will give us an error.

+makeExample('cb-jquery-plugin/ts/app/hero.component.ts', 'declare-jquery', 'app/hero.component.ts (declare jquery)')(format=".")

.l-main-section
<a id="drag"></a>
:marked
## Drag

`draggable` is a jQuery plugin that allows us to move an element on the screen. In the UI our admins will "drag" heroes and drop them on assignments.

`HeroComponent` is created to represent "draggable" hero elements.

+makeTabs(
`cb-jquery-plugin/ts/app/hero.component.ts,
cb-jquery-plugin/ts/app/hero.component.html`,
null,
`hero.component.ts,
hero.component.html`
)

:marked
We want to be careful not to access the DOM directly, so we are using `@ViewChild` to access the target element for the `draggable` plugin.

`@ViewChild('hero')` declares a reference to an element in the template with a matching `#hero` variable reference.

:marked
Now, we can go ahead and apply the draggable plugin to `this.hero.nativeElement` using familiar `jQuery` syntax.
+makeExample('cb-jquery-plugin/ts/app/hero.component.ts', 'add-plugin', 'app/hero.component.ts (add plugin)')(format=".")

:marked
We apply the plugin in the `AfterViewInit` lifecycle hook since we know the component view has been fully initialized at this point.

.l-main-section
<a id="drop"></a>
:marked
## Drop

`droppable` is used in tandem with `draggable` to create a drop-zone for dragged elements.

`HeroAssignmentComponent` represents an assignment that we can assign one or more heroes to using drag and drop.

+makeTabs(
`cb-jquery-plugin/ts/app/hero-assignment.component.ts,
cb-jquery-plugin/ts/app/hero-assignment.component.html`,
null,
`hero-assignment.component.ts,
hero-assignment.component.html`
)

:marked
Same as with `draggable`, we are applying the `droppable` plugin in `AfterViewInit`.

`droppable` lets us specify a callback that executes when a hero is dropped on the assignment. We use this callback to manage an array of assigned heroes whenever a new hero is assigned.

+makeExample('cb-jquery-plugin/ts/app/hero-assignment.component.ts', 'add-plugin', 'app/hero-assignment.component.ts (add plugin)')(format=".")

:marked
The final UI looks like this.

Admins can assign any given hero to multiple assignments by dragging and dropping.
figure.image-display
img(src="/resources/images/cookbooks/jquery-plugin/hero-assignments.png" alt="Hero Assignments")

:marked
[Back to top](#top)



Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.