├── 01-es6 ├── 1.variable-declarations.ts ├── 2.arrow-functions.ts ├── 3.destructuring.ts ├── 4.template-string.ts ├── 5.rest-arguments.ts ├── 6.spread-arguments.ts ├── 7.class.ts ├── 8.enhanced-object-literals.ts └── bootstrap.ts ├── 02-es7 ├── 1.decorators.ts └── bootstrap.ts ├── 03-typescript └── bootstrap.ts ├── 04-bootstrapping-angular └── bootstrap.ts ├── 05-components └── bootstrap.ts ├── 06-directives └── bootstrap.ts ├── 07-template-syntax └── bootstrap.ts ├── 13-pipes └── bootstrap.ts ├── 14-forms └── bootstrap.ts ├── README.md ├── game-tictactoe ├── app.ts ├── bootstrap.ts ├── components │ ├── board │ │ ├── board.css │ │ └── board.ts │ └── tictactoe.ts └── services │ └── GameService.ts ├── index.html ├── large-app ├── bootstrap.ts ├── components │ ├── app.css │ ├── app.ts │ ├── dashboard.ts │ └── rxjs_examples │ │ ├── rxjs-examples.ts │ │ └── rxjs.css ├── directives │ ├── Autofocus.ts │ └── directives.ts ├── pipes │ ├── CapitalizePipe.spec.ts │ ├── CapitalizePipe.ts │ ├── RxPipe.ts │ └── pipes.ts └── services │ ├── example-service.ts │ └── services.ts ├── rx-autosuggest ├── app.ts ├── bootstrap.ts ├── components │ └── search-github.ts ├── directives │ └── ac-autosuggest.ts └── services │ └── GithubService.ts ├── rx-draggable ├── app.ts ├── bootstrap.ts ├── components │ └── drag-element.ts └── directives │ └── draggable.ts ├── rx-timeflies ├── app.ts ├── bootstrap.ts ├── components │ └── timeflies.ts └── services │ └── Message.ts ├── server ├── db.js ├── express-server-example.js └── todo_api.js ├── simple-component ├── app.ts ├── bootstrap.ts └── home │ ├── home.css │ ├── home.html │ ├── home.spec.ts │ └── home.ts ├── simple-todo ├── app.ts ├── bootstrap.ts ├── components │ └── todo.ts └── services │ └── TodoService.ts └── webpack.config.js /01-es6/1.variable-declarations.ts: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * New ES6 variable declarations with `let` and `const` 4 | * 5 | */ 6 | 7 | 8 | console.log('-let-'); 9 | try { 10 | 11 | // `let` vs `var` 12 | // While `var` creates a variable scoped within its nearest parent function, 13 | // let scopes the variable to the nearest block 14 | function variableDeclarationsLetVar() { 15 | console.log('before: foo:', foo); // => undefined 16 | 17 | var foo = 'IamVar'; 18 | if (foo === 'IamVar') { 19 | let foo = 'IamLet'; 20 | } 21 | 22 | console.log('after: foo:', foo); // => 'IamVar' 23 | 24 | } 25 | 26 | variableDeclarationsLetVar(); 27 | console.log('after: variableDeclarationsLetVar():', foo); 28 | 29 | } catch(err) { console.error(err); } 30 | 31 | // `let` is also great when dealing with for-loops 32 | for (let i = 0; i < 2; ++i) { 33 | console.log('I am a loop with let i'); 34 | } 35 | 36 | // notice the same `let` variable is used in the same scope 37 | for (let i = 0; i < 2; ++i) { 38 | console.log('I am another loop with let i'); 39 | } 40 | 41 | console.log('-/let-\n'); 42 | console.log('-const-'); 43 | 44 | const amazing_people = ['PatrickJS', 'Lukas', 'Jeff', 'Dan']; 45 | 46 | console.log(amazing_people); 47 | 48 | amazing_people.push('Douglas Crockford'); 49 | amazing_people.push('Brendan Eich'); 50 | 51 | console.log(amazing_people); 52 | 53 | amazing_people = ['Blake Embrey', 'TJ Holowaychuk']; // shouldn't happen 54 | 55 | console.log('ref change', amazing_people); // warning happens 56 | 57 | console.log('-/const-\n'); 58 | -------------------------------------------------------------------------------- /01-es6/2.arrow-functions.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * New ES6 Arrow Functions allows us to preserve the context of our callbacks 3 | * 4 | */ 5 | 6 | 7 | let object = { 8 | collection: ['PatrickJS', 'Lukas', 'Jeff', 'Dan'], 9 | value: 'print some value:', 10 | method: function() { 11 | console.log(this.value, 'method'); 12 | this.collection.forEach(function(item) { 13 | console.log(this.value, item); 14 | }); 15 | } 16 | }; 17 | 18 | // notice how this.value inside of the forEach callback is `undefined` 19 | object.method(); 20 | 21 | 22 | let object2 = { 23 | collection: ['PatrickJS', 'Lukas', 'Jeff', 'Dan'], 24 | value: 'print some value:', 25 | method: function() { 26 | console.log(this.value, 'method'); 27 | this.collection.forEach((item) => { 28 | console.log(this.value, item); 29 | }); 30 | } 31 | }; 32 | 33 | // we fixed this by preserving the context for the callback 34 | object2.method(); 35 | 36 | /* 37 | * what's happening is the context of when the function was created is preserved in the function 38 | 39 | var object2 = { 40 | collection: ['PatrickJS', 'Lukas', 'Jeff', 'Dan'], 41 | value: 'print some value:', 42 | method: function() { 43 | var _self = this; 44 | console.log(this.value, 'method'); 45 | this.collection.forEach(function(item) { 46 | console.log(_self.value, item); 47 | }); 48 | } 49 | }; 50 | 51 | * here's another way to write this in ES5 52 | 53 | var object2 = { 54 | collection: ['PatrickJS', 'Lukas', 'Jeff', 'Dan'], 55 | value: 'print some value:', 56 | method: function() { 57 | console.log(this.value, 'method'); 58 | this.collection.forEach(function(item) { 59 | console.log(this.value, item); 60 | }.bind(this)); 61 | } 62 | }; 63 | */ 64 | 65 | 66 | function callingBack(callback) { 67 | callback(); 68 | } 69 | 70 | console.log('arrow callback pattern'); 71 | try { 72 | 73 | callingBack(object2.method); // this doesn't work and throws an error 74 | 75 | } catch(e) { console.error(e); } 76 | 77 | // very common pattern in order to preserve the context 78 | callingBack(() => object2.method()); 79 | -------------------------------------------------------------------------------- /01-es6/3.destructuring.ts: -------------------------------------------------------------------------------- 1 | 2 | // ES6 3 | 4 | // import {ClassObject} from 'framework/or/library'; 5 | 6 | // ES5 7 | 8 | // var lib = require('framework/or/library'); 9 | // var ClassObject = lib.ClassObject; 10 | 11 | 12 | var { x, y } = { x: 11, y: 8 }; // x = 11; y = 8 13 | console.log(x,y); 14 | 15 | 16 | // This declaration is equivalent to: 17 | var { x: x, y: y } = { x: 11, y: 8 }; 18 | 19 | console.log(x,y); 20 | 21 | // swap variables in ES5 22 | !function() { 23 | 24 | let a = 1; 25 | let b = 2; 26 | 27 | console.log(a, b); // 1,2 28 | 29 | let temp = b; // hold the value in a temp var 30 | b = a; 31 | a = temp 32 | 33 | console.log(a, b); // 2,1 34 | 35 | }(); 36 | 37 | // in ES6 we can use an array as our temp placeholder 38 | !function() { 39 | 40 | let a = 1; 41 | let b = 2; 42 | 43 | console.log(a, b); // 1,2 44 | 45 | [b, a] = [a, b]; 46 | 47 | console.log(a, b); // 2,1 48 | 49 | }(); 50 | 51 | // now it's look at it in ES5 52 | !function() { 53 | 54 | let a = 1; 55 | let b = 2; 56 | 57 | console.log(a, b); // 1,2 58 | 59 | 60 | let temp = [a, b]; 61 | b = temp[0]; 62 | a = temp[1]; 63 | 64 | console.log(a, b); // 2,1 65 | 66 | }(); 67 | 68 | -------------------------------------------------------------------------------- /01-es6/4.template-string.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * With ES6 we finally have multi-line string support 3 | */ 4 | 5 | let prevouly = '\n'+ 6 | '

Test

\n'+ 7 | '

testing

\n'+ 8 | ''; 9 | console.log('template strings prevouly\n', prevouly) 10 | 11 | // now we can use back-ticks 12 | 13 | let now = ` 14 |

Test

15 |

testing

16 | `; 17 | 18 | console.log('template strings now\n', now); 19 | 20 | // we also get interpolation features 21 | let feature = 'interpolation'; 22 | 23 | console.log(`testing out the new ${ feature } feature in ES6`) 24 | 25 | 26 | console.log('---------------------------------------------'); 27 | }(); 28 | !function() { 29 | console.log('---------------Default Arguments-------------'); 30 | /* 31 | * With ES6 we can declare a default argument 32 | */ 33 | 34 | function returnText(text = 'default text') { 35 | return 'return:\n' + text; 36 | } 37 | 38 | console.log(returnText()); 39 | 40 | console.log(returnText('now with text')); 41 | -------------------------------------------------------------------------------- /01-es6/5.rest-arguments.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * With ES6 we can convert the arguments Object into an array 3 | */ 4 | 5 | function printObjects(...objects) { 6 | objects.forEach(obj => { 7 | console.log('ES6 rest object:', obj); 8 | }); 9 | } 10 | 11 | printObjects({name: 'PatrickJS'}, {name: 'Lukas'}, {name: 'Jeff'}, {name: 'Dan'}); 12 | 13 | console.log('-es5-'); 14 | // in ES5 we would do 15 | function printObjectsES5(objects) { 16 | // re-assign objects as an Array of objects 17 | objects = Array.prototype.slice.call(arguments); 18 | 19 | objects.forEach(obj => { 20 | console.log('ES5 rest object:', obj); 21 | }); 22 | } 23 | 24 | printObjectsES5({name: 'PatrickJS'}, {name: 'Lukas'}, {name: 'Jeff'}, {name: 'Dan'}); 25 | 26 | -------------------------------------------------------------------------------- /01-es6/6.spread-arguments.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * With ES6 spread out an array into arguments for a function 3 | */ 4 | 5 | function f(x, y, z) { 6 | return x + y + z; 7 | } 8 | // Pass each elem of array as argument 9 | f(...[1, 2, 3]) === 6 10 | 11 | function printObjects(...objects) { 12 | console.log('rest object:', ...objects); 13 | } 14 | 15 | printObjects({name: 'PatrickJS'}, {name: 'Lukas'}, {name: 'Jeff'}, {name: 'Dan'}); 16 | 17 | -------------------------------------------------------------------------------- /01-es6/7.class.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * We now have sugar for a common pattern a lot of people use in ES5 3 | * we commented out the code because class declarations needs to be 4 | * declared at the top-level declaration 5 | */ 6 | 7 | 8 | 9 | // ES6 class 10 | class TestObject { 11 | 12 | } 13 | 14 | console.log('\n', TestObject.toString()) 15 | 16 | // ES5 we would do this 17 | function TestObjectES5() { 18 | 19 | } 20 | 21 | console.log('\n', TestObjectES5.toString()) 22 | 23 | 24 | 25 | 26 | // what happens when we add a method? 27 | 28 | // ES6 class 29 | class TestObject { 30 | method() { 31 | console.log('method'); 32 | } 33 | } 34 | 35 | console.log('\n', TestObject.prototype.method.toString()) 36 | 37 | // ES5 we would do this 38 | function TestObjectES5() { 39 | 40 | } 41 | 42 | TestObjectES5.prototype.method = function() { 43 | console.log('method'); 44 | } 45 | 46 | console.log('\n', TestObjectES5.prototype.method.toString()) 47 | 48 | 49 | 50 | // what happens when we subclass? 51 | 52 | class AnotherObject { 53 | 54 | } 55 | // ES6 class 56 | class TestObject extends AnotherObject { 57 | method() { 58 | console.log('method'); 59 | } 60 | } 61 | 62 | function AnotherObjectES5() { 63 | 64 | } 65 | 66 | // ES5 we would do this 67 | function TestObjectES5() { 68 | AnotherObjectES5.apply(this, arguments); 69 | 70 | } 71 | 72 | TestObjectES5.prototype = Object.create(AnotherObjectES5); 73 | TestObjectES5.prototype.constructor = TestObjectES5; 74 | 75 | TestObjectES5.prototype.method = function() { 76 | console.log('method'); 77 | } 78 | 79 | 80 | -------------------------------------------------------------------------------- /01-es6/8.enhanced-object-literals.ts: -------------------------------------------------------------------------------- 1 | 2 | function handler() { 3 | return 'handler'; 4 | } 5 | function get42() { 6 | return 42; 7 | } 8 | 9 | let object = { 10 | // Shorthand for ‘handler: handler’ 11 | handler, 12 | // Computed (dynamic) property names 13 | [ 'prop_' + get42() ]: 42 14 | }; 15 | 16 | console.log(object.handler()) 17 | console.log(object.prop_42()); 18 | 19 | 20 | /* 21 | 22 | function middleware(req, res) { 23 | db.find(req.params.id).then(data => { 24 | var jsonResponse = { 25 | ...data, 26 | }; 27 | jsonResponse[req.params.id] = Number(req.params.id); 28 | res.json(jsonResponse); 29 | 30 | }); 31 | } 32 | 33 | app.use('/api', middleware); 34 | 35 | function middleware2(req, res) { 36 | db.find(req.params.id).then(data => { 37 | 38 | res.json({ 39 | ...data, 40 | [req.params.id] = Number(req.params.id) 41 | }); 42 | 43 | }); 44 | } 45 | 46 | app.use('/api2', middleware2); 47 | 48 | */ 49 | -------------------------------------------------------------------------------- /01-es6/bootstrap.ts: -------------------------------------------------------------------------------- 1 | var app = (doc.querySelectorAll('app')[0]); 2 | app.innerHTML = 'open up your Console with CMD+Option+I'; 3 | 4 | /* 5 | * Intro: 6 | * 7 | * In ES6 we have a lot of new features added to JavaScript 8 | * so let's go over a few of the features that we will see 9 | * in Angular 2 10 | * please consider using https://babeljs.io/repl 11 | */ 12 | 13 | console.log('----------ES6 variable declarations----------'); 14 | require('./1.variable-declarations'); 15 | 16 | console.log('---------------Arrow Functions---------------'); 17 | require('./2.arrow-functions'); 18 | 19 | console.log('----------------Destructuring----------------'); 20 | require('./3.destructuring'); 21 | 22 | console.log('---------------Template String---------------'); 23 | require('./4.template-string'); 24 | 25 | console.log('----------------Rest Arguments--------------'); 26 | require('./5.rest-arguments'); 27 | 28 | console.log('---------------Spread Arguments--------------'); 29 | require('./6.spread-arguments'); 30 | 31 | console.log('---------------------Class-------------------'); 32 | require('./7.class'); 33 | 34 | console.log('------------Enhanced Object Literals---------'); 35 | require('./8.enhanced-object-literals'); 36 | 37 | 38 | // ES6 Modules 39 | // www.2ality.com/2014/09/es6-modules-final.html 40 | -------------------------------------------------------------------------------- /02-es7/1.decorators.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | function readonly(component) { 4 | component.writable = false; 5 | return component; 6 | } 7 | 8 | 9 | 10 | @readonly 11 | class App { 12 | 13 | } 14 | 15 | /* 16 | myDecorator(App); 17 | */ 18 | 19 | 20 | function configMyDecorator(config) { 21 | 22 | function myAttachDecorator(component) { 23 | component.attach = config.attach; 24 | return component; 25 | } 26 | 27 | return myAttachDecorator; 28 | } 29 | 30 | 31 | @configMyDecorator({ 32 | attach: 'something' 33 | }) 34 | class AnotherApp { 35 | 36 | } 37 | 38 | /* 39 | configMyDecorator(AnotherApp); 40 | */ 41 | -------------------------------------------------------------------------------- /02-es7/bootstrap.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | require('./1.decorators'); 5 | -------------------------------------------------------------------------------- /03-typescript/bootstrap.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | // Accessors 4 | class Employee { 5 | fullName: string; 6 | } 7 | 8 | var employee = new Employee(); 9 | 10 | employee.fullName = 'PatrickJS'; 11 | 12 | console.log(employee.fullName); 13 | 14 | 15 | class Animal { 16 | name: string; 17 | 18 | // Parameter properties 19 | // type string 20 | constructor(name: string) { 21 | this.name = name; 22 | } 23 | 24 | // Parameter properties 25 | // type number 26 | move(miles: number) { 27 | console.log(this.name + ' moved ' + miles + 'mi'); 28 | } 29 | } 30 | 31 | 32 | // Static Properties 33 | class Greeter { 34 | // property types 35 | standardGreeting: string = 'from @AngularClass'; 36 | greeting: string; 37 | 38 | // argument type 39 | constructor(message: string) { 40 | this.greeting = message; 41 | } 42 | 43 | greet() { 44 | if (this.greeting) { 45 | return 'Hello, ' + this.greeting; 46 | } else { 47 | return Greeter.standardGreeting; 48 | } 49 | } 50 | 51 | } 52 | 53 | 54 | var greeter = new Greeter('world'); 55 | var greeterStandard = new Greeter(); 56 | 57 | console.log(greeter.greet()); 58 | console.log(greeterStandard.greet()); 59 | 60 | 61 | 62 | // Public modifiers 63 | class App { 64 | // not needed 65 | // greeter: Greeter 66 | 67 | constructor(public greeter: Greeter) { 68 | 69 | // not needed 70 | // this.greeter = greeter 71 | 72 | } 73 | 74 | main() { 75 | this.greeter.greet(); 76 | } 77 | } 78 | 79 | var app = new App(greeter); 80 | 81 | app.main(); 82 | -------------------------------------------------------------------------------- /04-bootstrapping-angular/bootstrap.ts: -------------------------------------------------------------------------------- 1 | // Angular 2 2 | import * as angular from 'angular2/angular2'; 3 | import {Component, View} from 'angular2/angular2'; 4 | 5 | @Component({ 6 | // The selector is what angular internally uses 7 | // for `document.querySelectorAll(selector)` in our index.html 8 | // where, in this case, selector is the string 'app' 9 | selector: 'app' // 10 | }) 11 | @View({ 12 | // Every Angular template is first compiled by the browser before Angular runs it's compiler 13 | template: ` 14 | Hello from Angular 2 15 | ` 16 | }) 17 | class App { 18 | constructor() { 19 | console.log('Angular 2 App component'); 20 | } 21 | 22 | } 23 | 24 | /* 25 | * Bootstrap our Angular app with a top level component `App` and inject 26 | * our services/bindings into Angular's dependency injection 27 | */ 28 | angular.bootstrap(App, []); 29 | 30 | 31 | // index.html 32 | /* 33 | 34 | 35 | 36 | 37 | AngularClass 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | */ 52 | -------------------------------------------------------------------------------- /05-components/bootstrap.ts: -------------------------------------------------------------------------------- 1 | // Angular 2 2 | import {bootstrap} from 'angular2/angular2'; 3 | import {Component, View} from 'angular2/angular2'; 4 | 5 | @Component({ 6 | selector: 'ac-word' 7 | }) 8 | @View({ 9 | template: ` 10 | 11 | Hello from Angular Class 12 | 13 | ` 14 | }) 15 | class AcWord { 16 | constructor() { 17 | console.log('Angular Class Word component'); 18 | } 19 | 20 | } 21 | 22 | @Component({ 23 | selector: 'ac-box' 24 | }) 25 | @View({ 26 | directives: [ 27 | AcWord 28 | ], 29 | template: ` 30 |
31 | 32 |
33 | ` 34 | }) 35 | class AcBox { 36 | constructor() { 37 | console.log('Angular Class Box component'); 38 | } 39 | 40 | } 41 | 42 | @Component({ 43 | selector: 'app' 44 | }) 45 | @View({ 46 | // We need to tell Angular's compiler which directives are in our template. 47 | // Doing so will allow Angular to attach our behavior to an element 48 | directives: [ 49 | AcBox 50 | ], 51 | template: ` 52 |
53 | AngularClass 54 |
55 | 56 |
57 | 58 |
59 | 60 | 63 | 64 | ` 65 | }) 66 | class App { 67 | constructor() { 68 | console.log('Angular App component'); 69 | } 70 | } 71 | 72 | 73 | bootstrap(App, []); 74 | -------------------------------------------------------------------------------- /06-directives/bootstrap.ts: -------------------------------------------------------------------------------- 1 | // Angular 2 2 | import {bootstrap} from 'angular2/angular2'; 3 | import { 4 | Component, 5 | View, 6 | Directive, 7 | ElementRef, 8 | Attribute, 9 | NgStyle 10 | } from 'angular2/angular2'; 11 | 12 | 13 | @Directive({ 14 | // using [ ] means selecting an attribute 15 | selector: '[x-large]' 16 | }) 17 | class XLarge { 18 | constructor(element: ElementRef) { 19 | element.nativeElement.style.fontSize = 'x-large'; 20 | } 21 | } 22 | 23 | 24 | @Directive({ 25 | // using [ ] means selecting an attribute 26 | selector: '[set-font]' 27 | }) 28 | class SetFont { 29 | constructor(element: ElementRef, @Attribute('set-font') color: string) { 30 | element.nativeElement.style.color = color; 31 | } 32 | } 33 | 34 | 35 | @Component({ 36 | selector: 'app' 37 | }) 38 | @View({ 39 | directives: [ 40 | XLarge, 41 | SetFont, 42 | NgStyle 43 | ], 44 | template: ` 45 | Hello from AngularClass 46 | 47 |
48 | hidden text? 49 |
50 | 51 | Hello from AngularClass 52 | ` 53 | }) 54 | class App { 55 | constructor() { 56 | console.log('Angular App component'); 57 | } 58 | } 59 | 60 | 61 | bootstrap(App); 62 | -------------------------------------------------------------------------------- /07-template-syntax/bootstrap.ts: -------------------------------------------------------------------------------- 1 | // Angular 2 2 | import {bootstrap} from 'angular2/angular2'; 3 | import {Component, View, CORE_DIRECTIVES} from 'angular2/angular2'; 4 | 5 | 6 | @Component({ 7 | selector: 'app' 8 | }) 9 | @View({ 10 | directives: [ CORE_DIRECTIVES ], 11 | template: ` 12 | 17 | ` 18 | }) 19 | class App { 20 | collection: Array; 21 | 22 | constructor() { 23 | 24 | this.collection = [ 25 | 'item-1', 26 | 'item-2', 27 | 'item-3' 28 | ]; 29 | 30 | } 31 | } 32 | 33 | 34 | bootstrap(App); 35 | -------------------------------------------------------------------------------- /13-pipes/bootstrap.ts: -------------------------------------------------------------------------------- 1 | // Angular 2 2 | import {bootstrap} from 'angular2/angular2'; 3 | import {Component, View, Pipe} from 'angular2/angular2'; 4 | 5 | @Pipe({ 6 | name: 'capitalize' 7 | }) 8 | export class CapitalizePipe { 9 | 10 | transform(txt: string): any { 11 | return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); 12 | } 13 | 14 | } 15 | 16 | 17 | @Component({ 18 | selector: 'app' 19 | }) 20 | @View({ 21 | pipes: [ CapitalizePipe ], 22 | template: ` 23 |
24 |

{{ value | capitalize }}

25 |

{{ date | date:'mediumDate' }}

26 |

{{ grade | percent:'.2' }}

27 |
28 | ` 29 | }) 30 | class App { 31 | value: string = 'angular'; 32 | date: Date = new Date(); 33 | grade: number = 0.99; 34 | } 35 | 36 | 37 | 38 | bootstrap(App); 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /14-forms/bootstrap.ts: -------------------------------------------------------------------------------- 1 | // Angular 2 2 | import {bootstrap} from 'angular2/angular2'; 3 | import {Component, View} from 'angular2/angular2'; 4 | import {CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/angular2'; 5 | 6 | class UserModel { 7 | firstName: string; 8 | lastName: string; 9 | } 10 | 11 | @Component({ 12 | selector: 'app' 13 | }) 14 | @View({ 15 | directives: [ CORE_DIRECTIVES, FORM_DIRECTIVES ], 16 | template: ` 17 |
18 |

19 | 30 |

31 | 32 |

33 | 44 | 45 |

46 | 47 | 48 | 49 | 50 | 51 |
this.model = {{ model | json }}
52 | ` 53 | }) 54 | class App { 55 | model = new UserModel(); 56 | submit() { 57 | console.log('Submit Form', this.model); 58 | 59 | } 60 | } 61 | 62 | 63 | 64 | bootstrap(App); 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Angular 2 Fundamentals 4 | 5 |

6 | 7 | --- 8 | # Angular 2 Examples 9 | 10 | These are Angular 2 examples that you're able to grok different patterns done in Angular 2 11 | 12 | for the server please run 13 | `npm install express connect-history-api-fallback morgan body-parser cors --save` 14 | `node server/express-server-example.js` 15 | 16 | ___ 17 | 18 | enjoy -- **AngularClass** 19 | 20 | 21 |

22 | 23 | [![AngularClass](https://cloud.githubusercontent.com/assets/1016365/9863770/cb0620fc-5af7-11e5-89df-d4b0b2cdfc43.png "Angular Class")](https://angularclass.com) 24 | ##[AngularClass](https://angularclass.com) 25 | > Learn Angular in 2 days from the best 26 | -------------------------------------------------------------------------------- /game-tictactoe/app.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component} from 'angular2/angular2'; 5 | 6 | import {Tictactoe} from './components/tictactoe'; 7 | 8 | /* 9 | * App Component 10 | * our top level component that holds all of our components 11 | */ 12 | @Component({ 13 | selector: 'app', 14 | directives: [ Tictactoe ], 15 | template: ` 16 |
17 | 18 |
19 | ` 20 | }) 21 | export class App { 22 | constructor() { 23 | 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /game-tictactoe/bootstrap.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {bootstrap} from 'angular2/angular2'; 5 | 6 | import {FORM_PROVIDERS, ELEMENT_PROBE_PROVIDERS} from 'angular2/angular2' 7 | import {ROUTER_PROVIDERS} from 'angular2/router'; 8 | import {HTTP_PROVIDERS} from 'angular2/http'; 9 | 10 | import {App} from './app'; 11 | 12 | 13 | const APP_PROVIDERS = [ 14 | // These are dependencies of our App 15 | FORM_PROVIDERS, 16 | ROUTER_PROVIDERS, 17 | HTTP_PROVIDERS, 18 | ELEMENT_PROBE_PROVIDERS 19 | ]; 20 | /* 21 | * Bootstrap our Angular app with a top level component `App` and inject 22 | * our Universal/Platform services/bindings into Angular's dependency injection 23 | */ 24 | bootstrap( 25 | // Top Level Component 26 | App, 27 | // AppBindings 28 | APP_PROVIDERS 29 | ); 30 | -------------------------------------------------------------------------------- /game-tictactoe/components/board/board.css: -------------------------------------------------------------------------------- 1 | .board { 2 | margin: 100px auto; 3 | } 4 | 5 | .board .row .tile { 6 | border: 1px solid rgb(210, 210, 210); 7 | height: 100px; 8 | width: 100px; 9 | display: inline-block; 10 | cursor: pointer; 11 | float: left; 12 | margin-left: -1px; 13 | margin-bottom: -1px; 14 | } 15 | 16 | 17 | .board .row .x { 18 | background-image: url(data:image/png;base64,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); 19 | } 20 | 21 | .board .row .o { 22 | background-image: url(data:image/jpeg;base64,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); 23 | } 24 | 25 | .board .row .x, 26 | .board .row .o { 27 | cursor: default; 28 | background-size: 100px 100px; 29 | background-repeat: no-repeat; 30 | } 31 | 32 | 33 | .board .row::after { 34 | content: " "; 35 | clear: both; 36 | display: table; 37 | } 38 | 39 | 40 | .board .row .tile:hover { 41 | background-color: rgb(210, 210, 210); 42 | } 43 | -------------------------------------------------------------------------------- /game-tictactoe/components/board/board.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component, EventEmitter, CORE_DIRECTIVES} from 'angular2/angular2'; 5 | 6 | @Component({ 7 | selector: 'board', 8 | inputs: [ 'board' ], 9 | outputs: [ 'select' ], 10 | directives: [ CORE_DIRECTIVES ], 11 | styles: [ 12 | require('./board.css') // webpack require 13 | ], 14 | template:` 15 |
16 |
17 |
18 |
22 |
23 |
24 |
25 |
26 | ` 27 | }) 28 | export class Board { 29 | select: EventEmitter = new EventEmitter(); 30 | onChange() { 31 | console.log('change') 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /game-tictactoe/components/tictactoe.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component} from 'angular2/angular2'; 5 | import {CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/angular2'; 6 | import {ROUTER_DIRECTIVES} from 'angular2/router'; 7 | 8 | // Services 9 | import {GameService} from '../services/GameService'; 10 | 11 | // Components 12 | import {Board} from './board/board'; 13 | 14 | const ANGULAR_DIRECTIVES = [ 15 | // Angular's core directives 16 | CORE_DIRECTIVES, 17 | // Angular's form directives 18 | FORM_DIRECTIVES, 19 | // Angular's router 20 | ROUTER_DIRECTIVES 21 | ]; 22 | 23 | @Component({ 24 | selector: 'tictactoe', 25 | bindings: [ GameService ], 26 | directives: [ 27 | ANGULAR_DIRECTIVES, 28 | // 29 | Board 30 | ], 31 | template:` 32 |
33 |

Tic Tac Toe

34 |

{{ game.winner }} won!

35 |

draw

36 | 37 | 38 | 39 | 40 |
41 | ` 42 | }) 43 | export class Tictactoe { 44 | constructor(public game: GameService) { 45 | 46 | } 47 | 48 | reset() { 49 | this.game.dispose(); 50 | this.game = GameService.create(); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /game-tictactoe/services/GameService.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import {provide, Injectable} from 'angular2/angular2'; 3 | 4 | type Triple = [ string, string, string ]; // tuple type 5 | type Rows = [ Triple, Triple, Triple ]; 6 | type Point = { x: number; y: number }; 7 | 8 | @Injectable() 9 | export class GameService { 10 | 11 | board: Rows = [ 12 | ['', '', ''], 13 | ['', '', ''], 14 | ['', '', ''] 15 | ]; 16 | plays: Point[] = []; 17 | 18 | static create() { 19 | return new GameService(); 20 | } 21 | 22 | dispose() { 23 | this.board = null 24 | this.plays = null; 25 | } 26 | 27 | play(coord: Point) { 28 | const { x, y } = coord; 29 | if (!this.gameover && this.board[x][y] === '') { 30 | this.board[x][y] = this.player; 31 | } 32 | this.plays.push(coord); //TODO: create Rx Observable 33 | } 34 | 35 | get player() { 36 | return ['x', 'o'][this.plays.length % 2]; 37 | } 38 | 39 | get gameover() { 40 | return this.draw || this.winner !== ''; 41 | } 42 | 43 | get winner(): string { 44 | return getWinnerFromBoard(this.board); 45 | } 46 | 47 | get draw() { 48 | return this.plays.length === 9; 49 | } 50 | 51 | } 52 | 53 | export var GAMESERVICE_BINDINGS = [ 54 | provide(GameService, {useClass: GameService}) 55 | ]; 56 | 57 | // Pure functions 58 | 59 | export function getWinnerFromBoard(board: Rows): string { 60 | const allWinningLists = [].concat( 61 | board, // rows 62 | zip(board), // columns 63 | diagonals(board) // diagonals 64 | ); 65 | 66 | return allWinningLists.reduce(getWinnerFromList, ''); 67 | } 68 | 69 | export function getWinnerFromList(winner: string, list: Triple) { 70 | if (winner) return winner; 71 | if (list.every(s => s == 'o')) return 'o'; 72 | if (list.every(s => s == 'x')) return 'x'; 73 | return ''; 74 | } 75 | 76 | export function zip(arrays: Rows) { 77 | return arrays[0].map((_, i) => arrays.map(array => array[i])); 78 | } 79 | 80 | export function diagonals(rows: Rows) { 81 | return [ 82 | rows.map((row, index) => row[index]), // left to right diagonal 83 | rows.map((row, index) => row[row.length - 1 - index]) // right to left diagonal 84 | ]; 85 | } 86 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular 2 Examples by @gdi2990 from @AngularClass 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | Loading... 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /large-app/bootstrap.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {bootstrap} from 'angular2/angular2'; 5 | 6 | 7 | /* 8 | * Common Injectables 9 | * our custom helper injectables to configure our app differently using the dependency injection system 10 | */ 11 | // import { 12 | // JIT_CHANGEDETECTION_BINDINGS, 13 | // DYNAMIC_CHANGEDETECTION_BINDINGS, 14 | // PREGENERATED_CHANGEDETECTION_BINDINGS, 15 | // BEST_CHANGEDETECTION_BINDINGS 16 | // } from '../common/change_detection_bindings'; 17 | // import { 18 | // HTML5_LOCATION_BINDINGS, 19 | // HASH_LOCATION_BINDINGS 20 | // } from '../common/location_bindings'; 21 | 22 | /* 23 | * Angular Modules 24 | */ 25 | import {FORM_PROVIDERS} from 'angular2/angular2'; 26 | import {HTTP_PROVIDERS} from 'angular2/http'; 27 | import {ROUTER_PROVIDERS} from 'angular2/router'; 28 | 29 | /* 30 | * App Services 31 | * our collection of injectables services 32 | */ 33 | import {APP_SERVICES_BINDINGS} from './services/services'; 34 | 35 | 36 | /* 37 | * App Component 38 | * our top level component that holds all of our components 39 | */ 40 | import {App} from './components/app'; 41 | 42 | 43 | /* 44 | * Universal injectables 45 | */ 46 | const UNIVERSAL_BINDINGS = [ 47 | // Angular's http/form/router services/bindings 48 | HTTP_PROVIDERS, 49 | FORM_PROVIDERS, 50 | ROUTER_PROVIDERS, 51 | 52 | // Our collection of services from /services 53 | APP_SERVICES_BINDINGS 54 | ]; 55 | 56 | /* 57 | * Platform injectables 58 | */ 59 | const PLATFORM_BINDINGS = [ 60 | // if we want to explicit change detection 61 | // BEST_CHANGEDETECTION_BINDINGS, 62 | 63 | // if we want to use hashBash url for the router 64 | // HASH_LOCATION_BINDINGS 65 | ]; 66 | 67 | const APP_BINDINGS = [ 68 | UNIVERSAL_BINDINGS, 69 | PLATFORM_BINDINGS 70 | ]; 71 | 72 | /* 73 | * Bootstrap our Angular app with a top level component `App` and inject 74 | * our Universal/Platform services/bindings into Angular's dependency injection 75 | */ 76 | bootstrap( 77 | // Top Level Component 78 | App, 79 | // AppBindings 80 | APP_BINDINGS 81 | ); 82 | -------------------------------------------------------------------------------- /large-app/components/app.css: -------------------------------------------------------------------------------- 1 | .top-nav { 2 | height: 56px; 3 | min-height: 56px; 4 | padding: 0 16px; 5 | box-shadow: 0 2px 5px 0 rgba(0,0,0,0.26); 6 | } 7 | 8 | .top-nav h1 { 9 | width: 200px; 10 | float: left; 11 | font-size: 16px; 12 | font-weight: 400; 13 | letter-spacing: 0.005em; 14 | } 15 | .top-nav .logo { 16 | line-height:56px; 17 | display:inline-block; 18 | color:#FFF; 19 | padding:0 5px; 20 | font-weight:400; 21 | font-size:16px; 22 | position:relative 23 | } 24 | 25 | 26 | .top-nav ul { 27 | list-style-type: none; 28 | margin: 0; 29 | padding: 0 20px; 30 | } 31 | 32 | .top-nav ul li { 33 | margin: 0; 34 | } 35 | .l-left { 36 | float: left; 37 | } 38 | 39 | .top-nav { 40 | font-family:'Roboto',"Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 41 | } 42 | 43 | .top-nav .top-nav-button{ 44 | line-height:56px; 45 | display:inline-block; 46 | color:#FFF; 47 | text-decoration:none; 48 | padding:0 10px; 49 | text-transform:uppercase; 50 | font-weight:400; 51 | font-size:16px; 52 | border:none; 53 | background:none; 54 | border-radius:0; 55 | position:relative 56 | } 57 | 58 | 59 | .top-nav .top-nav-button:hover{ 60 | background-color: rgba(158, 158, 158, 0.2); 61 | } 62 | 63 | a:active, a:hover { 64 | outline: 0px none; 65 | } 66 | 67 | .ac-default-theme { 68 | background-color: rgb(25,118,210); 69 | color: rgb(255,255,255); 70 | } 71 | 72 | 73 | [layout=row] { 74 | -webkit-flex-direction: row; 75 | -ms-flex-direction: row; 76 | flex-direction: row; 77 | } 78 | [layout] { 79 | box-sizing: border-box; 80 | display: -webkit-flex; 81 | display: -moz-flex; 82 | display: -ms-flexbox; 83 | display: flex; 84 | } 85 | -------------------------------------------------------------------------------- /large-app/components/app.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | /* 4 | * Angular 2 5 | */ 6 | import {Component, View} from 'angular2/angular2'; 7 | import {RouteConfig} from 'angular2/router'; 8 | 9 | /* 10 | * Directives 11 | */ 12 | import {CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/angular2'; 13 | import {ROUTER_DIRECTIVES} from 'angular2/router'; 14 | // Import all of our custom app directives 15 | import {APP_DIRECTIVES} from '../directives/directives'; 16 | 17 | /* 18 | * App Pipes 19 | * our collection of pipes registry 20 | */ 21 | import {APP_PIPES} from '../pipes/pipes'; 22 | 23 | /* 24 | * Components 25 | */ 26 | // We use a folder if we want separate files 27 | import {Home} from '../../simple-component/home/home'; 28 | // Otherwise we only use one file for a component 29 | import {Dashboard} from './dashboard'; 30 | // A simple example of a Component using a Service 31 | import {Todo} from '../../simple-todo/components/todo'; 32 | 33 | // RxJs examples 34 | import {RxJsExamples} from './rxjs_examples/rxjs-examples'; 35 | 36 | // Use webpack's `require` to get files as a raw string using raw-loader 37 | const APP_STYLES = require('./app.css'); 38 | 39 | /* 40 | * App Component 41 | * Top Level Component 42 | * Simple router component example 43 | */ 44 | @Component({ 45 | selector: 'app', // without [ ] means we are selecting the tag directly 46 | viewBindings: [] 47 | }) 48 | @View({ 49 | pipes: [ APP_PIPES ], 50 | directives: [ APP_DIRECTIVES ], 51 | styles: [ APP_STYLES ], 52 | template: ` 53 |
54 |
55 | Angular2 56 | 57 | 71 |
72 |
73 | 74 |
75 | 76 |
77 | 78 | 81 | ` 82 | }) 83 | @RouteConfig([ 84 | { path: '/', as: 'Home', component: Home }, 85 | { path: '/dashboard', as: 'Dashboard', component: Dashboard }, 86 | { path: '/todo', as: 'Todo', component: Todo }, 87 | { path: '/rxjs-examples/...', as: 'RxjsExamples', component: RxJsExamples } 88 | ]) 89 | export class App { 90 | name: string; 91 | constructor() { 92 | this.name = 'angular'; // used in logo 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /large-app/components/dashboard.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | /* 4 | * Angular 2 5 | */ 6 | import {Component, View, Directive, ElementRef} from 'angular2/angular2'; 7 | import {Renderer} from 'angular2/render'; 8 | 9 | /* 10 | * TODO: refactor 11 | * simple example directive that should be in `/directives` folder 12 | */ 13 | @Directive({ 14 | selector: '[x-large]' // using [ ] means selecting attributes 15 | }) 16 | class XLarge { 17 | constructor(element: ElementRef, renderer: Renderer) { 18 | // simple DOM manipulation to set font size to x-large 19 | renderer.setElementStyle(element, 'fontSize', 'x-large'); 20 | } 21 | } 22 | 23 | // Simple component with custom directive example 24 | @Component({ 25 | selector: 'dashboard' 26 | }) 27 | @View({ 28 | directives: [ XLarge ], 29 | styles: [` 30 | span[x-large] { 31 | color: red; 32 | } 33 | `], 34 | template: ` 35 |
36 |

Dashboard

37 | Extra Large Font Directive 38 |
39 | ` 40 | }) 41 | export class Dashboard { 42 | constructor() { 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /large-app/components/rxjs_examples/rxjs-examples.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component, View, NgClass } from 'angular2/angular2'; 5 | import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router'; 6 | 7 | import {SearchGithub} from '../../../rx-autosuggest/components/search-github'; 8 | import {Timeflies} from '../../../rx-timeflies/components/timeflies'; 9 | import {Tictactoe} from '../../../game-tictactoe/components/tictactoe'; 10 | //import {DragElement} from '../../../rx-draggable/components/drag-element'; 11 | 12 | 13 | @Component({ 14 | selector: 'rxjs-examples' 15 | }) 16 | @RouteConfig([ 17 | { path: '/', redirectTo: '/search' }, 18 | { path: '/search', as: 'Search', component: SearchGithub}, 19 | { path: '/timeflies', as: 'Timeflies', component: Timeflies }, 20 | { path: '/tictactoe', as: 'Tictactoe', component: Tictactoe }, 21 | //{ path: '/draggable', as: 'Draggable', component: DragElement} 22 | ]) 23 | @View({ 24 | directives: [ ROUTER_DIRECTIVES, NgClass ], 25 | // include our .css file 26 | styles: [ 27 | // Use webpack's `require` to get files as a raw string using raw-loader 28 | require('./rxjs.css') 29 | ], 30 | template: ` 31 |
32 | 62 | 63 |
64 |
65 | 66 |
67 |
68 | 69 |
70 | ` 71 | }) 72 | export class RxJsExamples { 73 | active: number = 0; 74 | } 75 | -------------------------------------------------------------------------------- /large-app/components/rxjs_examples/rxjs.css: -------------------------------------------------------------------------------- 1 | .rxjs-menu, 2 | .rxjs-menu ul { 3 | list-style: none; 4 | padding: 0; 5 | } 6 | .rxjs-menu li { 7 | margin: 0; 8 | } 9 | .rxjs-menu > li:nth-child(1) { 10 | border-top: none; 11 | } 12 | .rxjs-menu .ac-button { 13 | border-radius: 0; 14 | color: inherit; 15 | cursor: pointer; 16 | display: block; 17 | line-height: 40px; 18 | margin: 0; 19 | max-height: 40px; 20 | overflow: hidden; 21 | padding: 0px 16px; 22 | text-align: left; 23 | text-decoration: none; 24 | white-space: normal; 25 | width: 100%; 26 | } 27 | .rxjs-menu ac-select { 28 | 29 | /* Override md-select margins. With margins the menu will look incorrect and causes mobile list 30 | to not be scrollable. 31 | */ 32 | margin: 0; 33 | width: 100%; 34 | } 35 | .rxjs-menu .ac-button.active { 36 | color: #03a9f4; 37 | } 38 | ul.rxjs-menu li:hover { 39 | background: rgba(0,0,0,0.1); 40 | } 41 | 42 | .side-nav { 43 | background: #FFF; 44 | box-shadow: 3px 0 6px rgba(0,0,0,0.3); 45 | width: 260px; 46 | bottom: 0; 47 | overflow: auto; 48 | } 49 | 50 | nav { 51 | align-items: stretch; 52 | } 53 | 54 | [layout] { 55 | box-sizing: border-box; 56 | display: -webkit-flex; 57 | display: -moz-flex; 58 | display: -ms-flexbox; 59 | display: flex; 60 | } 61 | 62 | [layout=column] { 63 | -webkit-flex-direction: column; 64 | -ms-flex-direction: column; 65 | flex-direction: column; 66 | } 67 | 68 | .wide{ 69 | width:100%; 70 | } 71 | 72 | .rxjs-content { 73 | align-items: stretch; 74 | display: block; 75 | position: relative; 76 | overflow: auto; 77 | -webkit-overflow-scrolling: touch; 78 | } 79 | -------------------------------------------------------------------------------- /large-app/directives/Autofocus.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import {Directive, ElementRef} from 'angular2/angular2'; 3 | import {Renderer} from 'angular2/render'; 4 | 5 | // Simple example directive that fixes autofocus problem with multiple views 6 | @Directive({ 7 | selector: '[autofocus]' // using [ ] means selecting attributes 8 | }) 9 | export class Autofocus { 10 | constructor(el: ElementRef, renderer: Renderer) { 11 | // autofocus fix for multiple views 12 | renderer.invokeElementMethod(el, 'focus', []); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /large-app/directives/directives.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /* 3 | * Angular 2 4 | */ 5 | import {CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/angular2'; 6 | import {ROUTER_DIRECTIVES} from 'angular2/router'; 7 | 8 | /* 9 | * App 10 | */ 11 | import {Autofocus} from './Autofocus'; 12 | 13 | export * from './Autofocus'; 14 | // global App only directives 15 | export var SERVICES_DIRECTIVES: Array = [ 16 | Autofocus 17 | ]; 18 | 19 | // global Angular core and other Angular module directives (form/router) 20 | export var ANGULAR_DIRECTIVES: Array = [ 21 | // Angular's core directives 22 | CORE_DIRECTIVES, 23 | 24 | // Angular's form directives 25 | FORM_DIRECTIVES, 26 | 27 | // Angular's router 28 | ROUTER_DIRECTIVES, 29 | ]; 30 | 31 | // global App only directives 32 | export var APP_DIRECTIVES: Array = [ 33 | ANGULAR_DIRECTIVES, 34 | SERVICES_DIRECTIVES 35 | ]; 36 | 37 | -------------------------------------------------------------------------------- /large-app/pipes/CapitalizePipe.spec.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import {CapitalizePipe} from './CapitalizePipe'; 3 | 4 | describe('Capitalize', () => { 5 | 6 | describe('CapitalizePipe', () => { 7 | var subject; 8 | var result; 9 | var pipe; 10 | 11 | beforeEach(() => { 12 | pipe = new CapitalizePipe(); 13 | }); 14 | afterEach(() => { 15 | expect(subject).toEqual(result); 16 | }); 17 | 18 | describe('#support', () => { 19 | 20 | it('should support string', () => { 21 | subject = pipe.supports('yolo'); 22 | result = true; 23 | }); 24 | 25 | it('should not support null', () => { 26 | subject = pipe.supports(null); 27 | result = false; 28 | }); 29 | 30 | it('should not support NaN', () => { 31 | subject = pipe.supports(NaN); 32 | result = false; 33 | }); 34 | 35 | it('should not support new Object()', () => { 36 | subject = pipe.supports(new Object()); 37 | result = false; 38 | }); 39 | 40 | it('should not support function(){}', () => { 41 | subject = pipe.supports(function(){}); 42 | result = false; 43 | }); 44 | 45 | }); 46 | 47 | describe('#transform', () => { 48 | it('should transform string to Capitalized versions', () => { 49 | subject = pipe.transform('yolo'); 50 | result = 'Yolo'; 51 | }); 52 | 53 | it('should transform all strings to Capitalized versions', () => { 54 | var str = 'what does the scouter say about its power level'; 55 | 56 | subject = pipe.transform(str, true); 57 | result = 'What Does The Scouter Say About Its Power Level'; 58 | }); 59 | 60 | }); 61 | 62 | 63 | describe('#capitalizeWord', () => { 64 | it('should capitalized a word', () => { 65 | subject = pipe.capitalizeWord('something'); 66 | result = 'Something'; 67 | }); 68 | 69 | it('should only capitalized first char', () => { 70 | subject = pipe.capitalizeWord('something something something'); 71 | result = 'Something something something'; 72 | }); 73 | 74 | }); 75 | 76 | 77 | }); 78 | 79 | }); 80 | -------------------------------------------------------------------------------- /large-app/pipes/CapitalizePipe.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import {Pipe} from 'angular2/angular2'; 3 | 4 | // Check if the value is supported for the pipe 5 | export function isString(txt): boolean { 6 | return typeof txt === 'string'; 7 | } 8 | 9 | // Simple example of a Pipe 10 | @Pipe({ 11 | name: 'capitalize' 12 | }) 13 | export class CapitalizePipe { 14 | regexp: RegExp = /([^\W_]+[^\s-]*) */g; 15 | 16 | supports(txt): boolean { 17 | return isString(txt); 18 | } 19 | 20 | transform(value: string, args?: Array): any { 21 | return (!value) ? '' : 22 | (!args) ? 23 | this.capitalizeWord(value) : 24 | value.replace(this.regexp, this.capitalizeWord); 25 | } 26 | 27 | capitalizeWord(txt: string): string { 28 | return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); 29 | 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /large-app/pipes/RxPipe.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import {Pipe, ChangeDetectorRef} from 'angular2/angular2'; 3 | import {AsyncPipe, Observable} from "angular2/angular2"; 4 | import * as Rx from '@reactivex/rxjs'; 5 | 6 | export function isObservable(obs) { 7 | return obs && typeof obs.subscribe === 'function'; 8 | } 9 | 10 | export class RxStrategy { 11 | createSubscription(async, updateLatestValue) { 12 | return async.subscribe(updateLatestValue, e => { throw e; }); 13 | } 14 | 15 | dispose(subscription) { 16 | subscription.dispose(); 17 | } 18 | 19 | onDestroy(subscription) { 20 | subscription.dispose(); 21 | 22 | } 23 | } 24 | 25 | export const RX_STRATEGY: RxStrategy = new RxStrategy(); 26 | 27 | @Pipe({ 28 | name: 'rx' 29 | }) 30 | export class RxPipe extends AsyncPipe { 31 | constructor(public _ref: ChangeDetectorRef) { 32 | super(_ref); 33 | } 34 | 35 | supports(obs): boolean { 36 | return isObservable(obs); 37 | } 38 | 39 | _selectStrategy(obj: Observable | Promise) { 40 | return RX_STRATEGY; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /large-app/pipes/pipes.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /* 3 | * Angular 2 4 | */ 5 | import {Pipe} from 'angular2/angular2'; 6 | 7 | /* 8 | * App Pipes 9 | */ 10 | import {CapitalizePipe} from './CapitalizePipe'; 11 | import {RxPipe} from './RxPipe'; 12 | 13 | 14 | export * from './CapitalizePipe'; 15 | export * from './RxPipe'; 16 | export const APP_PIPES = [ 17 | CapitalizePipe, 18 | RxPipe 19 | ]; 20 | -------------------------------------------------------------------------------- /large-app/services/example-service.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import {Injectable} from 'angular2/angular2'; 4 | import {Http} from 'angular2/http'; 5 | import * as Rx from '@reactivex/rxjs'; 6 | 7 | 8 | @Injectable() 9 | export class ExampleService { 10 | constructor(public http: Http) { 11 | 12 | } 13 | } 14 | 15 | export const EXAMPLE_SERVICE_BINDINGS = [ 16 | ExampleService 17 | ]; 18 | -------------------------------------------------------------------------------- /large-app/services/services.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import {bind} from 'angular2/angular2'; 4 | import {EXAMPLE_SERVICE_BINDINGS} from './example-service'; 5 | 6 | 7 | export * from './example-service'; 8 | // Include bindings that you want to have globally throughout our app 9 | export var APP_SERVICES_BINDINGS: Array = [ 10 | EXAMPLE_SERVICE_BINDINGS 11 | ]; 12 | -------------------------------------------------------------------------------- /rx-autosuggest/app.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component} from 'angular2/angular2'; 5 | 6 | import {SearchGithub} from './components/search-github'; 7 | 8 | /* 9 | * App Component 10 | * our top level component that holds all of our components 11 | */ 12 | @Component({ 13 | selector: 'app', 14 | directives: [ SearchGithub ], 15 | template: ` 16 |
17 | 18 |
19 | ` 20 | }) 21 | export class App { 22 | constructor() { 23 | 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /rx-autosuggest/bootstrap.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {bootstrap} from 'angular2/angular2'; 5 | 6 | import {FORM_PROVIDERS, ELEMENT_PROBE_PROVIDERS} from 'angular2/angular2' 7 | import {ROUTER_PROVIDERS} from 'angular2/router'; 8 | import {HTTP_PROVIDERS} from 'angular2/http'; 9 | 10 | import {App} from './app'; 11 | 12 | 13 | const APP_PROVIDERS = [ 14 | // These are dependencies of our App 15 | FORM_PROVIDERS, 16 | ROUTER_PROVIDERS, 17 | HTTP_PROVIDERS, 18 | ELEMENT_PROBE_PROVIDERS 19 | ]; 20 | /* 21 | * Bootstrap our Angular app with a top level component `App` and inject 22 | * our Universal/Platform services/bindings into Angular's dependency injection 23 | */ 24 | bootstrap( 25 | // Top Level Component 26 | App, 27 | // AppProviders 28 | APP_PROVIDERS 29 | ); 30 | -------------------------------------------------------------------------------- /rx-autosuggest/components/search-github.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component} from 'angular2/angular2'; 5 | import {CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/angular2'; 6 | 7 | import {AcAutosuggestGithub} from '../directives/ac-autosuggest'; 8 | 9 | @Component({ 10 | selector: 'search-github', 11 | directives: [ CORE_DIRECTIVES, FORM_DIRECTIVES, AcAutosuggestGithub ], 12 | template: ` 13 |
14 |

Search Github repos

15 | 16 |
17 | 18 | 24 | 28 |
29 | 30 |
31 | 32 | 37 | 38 |
39 |
40 | ` 41 | }) 42 | export class SearchGithub { 43 | repos: Array = []; 44 | loading: boolean = false; 45 | 46 | constructor() { 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /rx-autosuggest/directives/ac-autosuggest.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Directive, View, EventEmitter, ElementRef} from 'angular2/angular2'; 5 | 6 | 7 | 8 | // RxJs 9 | import * as Rx from '@reactivex/rxjs'; 10 | 11 | import {GithubService} from '../services/GithubService'; 12 | 13 | 14 | declare var zone: Zone; 15 | 16 | @Directive({ 17 | selector: 'input[type=text][ac-autosuggest-github]', 18 | outputs: [ 'results', 'loading' ], 19 | providers: [ GithubService ] 20 | }) 21 | export class AcAutosuggestGithub { 22 | results: EventEmitter = new EventEmitter(); 23 | loading: EventEmitter = new EventEmitter(); 24 | 25 | constructor(private el: ElementRef, public github: GithubService) { 26 | 27 | } 28 | 29 | // Lifecycle hook 30 | onInit() { 31 | 32 | (Rx).Observable.fromEvent(this.el.nativeElement, 'keyup') 33 | .map(e => e.target.value) // Project the text from the input 34 | .filter(text => text.length > 2) // Only if the text is longer than 2 characters 35 | .debounceTime(250) // Pause for 250ms 36 | .distinctUntilChanged() // Only if the value has changed 37 | .do(zone.bind(() => this.loading.next(true))) 38 | .flatMap(query => this.github.search(query)) // send query to search service 39 | .do(zone.bind(() => this.loading.next(false))) 40 | // here is the real action 41 | .subscribe( 42 | // onNext 43 | zone.bind(repos => { 44 | // fire "results" event 45 | // the Search component is the listener 46 | this.results.next(repos); 47 | }), 48 | // onError 49 | zone.bind(err => { 50 | console.log(err); 51 | this.results.next(['ERROR, see console']); 52 | }), 53 | // onComplete 54 | () => { 55 | console.log('complete'); 56 | } 57 | )//subscribe 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /rx-autosuggest/services/GithubService.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import {provide, Injectable} from 'angular2/angular2'; 4 | import {Http} from 'angular2/http'; 5 | import * as Rx from '@reactivex/rxjs'; 6 | 7 | 8 | @Injectable() 9 | export class GithubService { 10 | url: string = 'https://api.github.com/search/repositories?q='; 11 | constructor(public http: Http) { 12 | 13 | } 14 | 15 | /** 16 | * @returns an Observable of repository names 17 | */ 18 | search(query: string): Rx.Observable { 19 | return this.http.get(this.url + query) 20 | .map(res => res.json()) // make json 21 | .map(res => res.items) // extract "items" only 22 | .filter(repos => repos); // only if there are results 23 | } 24 | } 25 | 26 | export var GITHUB_PROVIDERS: Array = [ 27 | provide(GithubService, {useClass: GithubService}) 28 | ]; 29 | -------------------------------------------------------------------------------- /rx-draggable/app.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component, View} from 'angular2/angular2'; 5 | 6 | import {DragElement} from './components/drag-element'; 7 | 8 | /* 9 | * App Component 10 | * our top level component that holds all of our components 11 | */ 12 | @Component({ 13 | selector: 'app' 14 | }) 15 | @View({ 16 | directives: [ DragElement ], 17 | template: ` 18 |
19 | 20 |
21 | ` 22 | }) 23 | export class App { 24 | constructor() { 25 | 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /rx-draggable/bootstrap.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {bootstrap} from 'angular2/angular2'; 5 | 6 | import {FORM_PROVIDERS, ELEMENT_PROBE_PROVIDERS} from 'angular2/angular2' 7 | import {ROUTER_PROVIDERS} from 'angular2/router'; 8 | import {HTTP_PROVIDERS} from 'angular2/http'; 9 | 10 | import {App} from './app'; 11 | 12 | 13 | const APP_PROVIDERS = [ 14 | // These are dependencies of our App 15 | FORM_PROVIDERS, 16 | ROUTER_PROVIDERS, 17 | HTTP_PROVIDERS, 18 | ELEMENT_PROBE_PROVIDERS 19 | ]; 20 | /* 21 | * Bootstrap our Angular app with a top level component `App` and inject 22 | * our Universal/Platform services/bindings into Angular's dependency injection 23 | */ 24 | bootstrap( 25 | // Top Level Component 26 | App, 27 | // AppProviders 28 | APP_PROVIDERS 29 | ); 30 | -------------------------------------------------------------------------------- /rx-draggable/components/drag-element.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component, View} from 'angular2/angular2'; 5 | 6 | // Directives 7 | import {Draggable} from '../directives/draggable'; 8 | 9 | @Component({ 10 | selector: 'drag-element', 11 | directives: [ Draggable ], 12 | styles: [` 13 | [draggable] { 14 | -webkit-transform: translate3d(0, 0, 0); 15 | -moz-transform: translate3d(0, 0, 0); 16 | -ms-transform: translate3d(0, 0, 0); 17 | transform: translate3d(0, 0, 0); 18 | background-image: url(https://cdn.rawgit.com/Reactive-Extensions/rx.angular.js/master/examples/draganddrop/logo.png); 19 | background-repeat: no-repeat; 20 | background-position: center; 21 | background-size: contain; 22 | height: 200px; 23 | width: 200px; 24 | color: #000000; 25 | border: 1px solid #666666; 26 | padding: 10px; 27 | } 28 | `], 29 | template: ` 30 | 31 |
32 | Draggable Div 33 |
34 | 35 | ` 36 | }) 37 | export class DragElement { 38 | constructor() { 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /rx-draggable/directives/draggable.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import {Directive, EventEmitter, HostListener} from 'angular2/angular2'; 4 | import {DOM} from 'angular2/src/core/dom/dom_adapter'; 5 | import {ElementRef} from 'angular2/core'; 6 | 7 | 8 | @Directive({ 9 | selector: '[draggable]' 10 | }) 11 | export class Draggable { 12 | mousedrag; 13 | mouseup = new EventEmitter(); 14 | mousedown = new EventEmitter(); 15 | mousemove = new EventEmitter(); 16 | 17 | @HostListener('mouseup', ['$event']) 18 | onMouseup(event) { this.mouseup.next(event); } 19 | 20 | @HostListener('mousedown', ['$event']) 21 | onMousedown(event) { this.mousedown.next(event); } 22 | 23 | @HostListener('mousemove', ['$event']) 24 | onMousemove(event) { this.mousemove.next(event); } 25 | 26 | constructor(public element: ElementRef) { 27 | this.element.nativeElement.style.position = 'relative'; 28 | this.element.nativeElement.style.cursor = 'pointer'; 29 | 30 | this.mousedrag = this.mousedown.toRx().map(event => { 31 | event.preventDefault(); 32 | return { 33 | left: event.clientX - this.element.nativeElement.getBoundingClientRect().left, 34 | top: event.clientY - this.element.nativeElement.getBoundingClientRect().top 35 | }; 36 | }) 37 | .flatMap(imageOffset => this.mousemove.toRx().map(pos => ({ 38 | top: pos.clientY - imageOffset.top, 39 | left: pos.clientX - imageOffset.left 40 | })) 41 | .takeUntil(this.mouseup.toRx())); 42 | 43 | } 44 | 45 | 46 | onInit() { 47 | this.mousedrag.subscribe({ 48 | next: pos => { 49 | // Update position 50 | this.element.nativeElement.style.top = pos.top + 'px'; 51 | this.element.nativeElement.style.left = pos.left + 'px'; 52 | } 53 | }); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /rx-timeflies/app.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component} from 'angular2/angular2'; 5 | 6 | import {Timeflies} from './components/timeflies'; 7 | 8 | /* 9 | * App Component 10 | * our top level component that holds all of our components 11 | */ 12 | @Component({ 13 | selector: 'app', 14 | directives: [ Timeflies ], 15 | template: ` 16 |
17 | 18 |
19 | ` 20 | }) 21 | export class App { 22 | constructor() { 23 | 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /rx-timeflies/bootstrap.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {bootstrap} from 'angular2/angular2'; 5 | 6 | import {FORM_PROVIDERS, ELEMENT_PROBE_PROVIDERS} from 'angular2/angular2' 7 | import {ROUTER_PROVIDERS} from 'angular2/router'; 8 | import {HTTP_PROVIDERS} from 'angular2/http'; 9 | 10 | import {App} from './app'; 11 | 12 | 13 | const APP_PROVIDERS = [ 14 | // These are dependencies of our App 15 | FORM_PROVIDERS, 16 | ROUTER_PROVIDERS, 17 | HTTP_PROVIDERS, 18 | ELEMENT_PROBE_PROVIDERS 19 | ]; 20 | /* 21 | * Bootstrap our Angular app with a top level component `App` and inject 22 | * our Universal/Platform services/bindings into Angular's dependency injection 23 | */ 24 | bootstrap( 25 | // Top Level Component 26 | App, 27 | // AppProviders 28 | APP_PROVIDERS 29 | ); 30 | -------------------------------------------------------------------------------- /rx-timeflies/components/timeflies.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component, ElementRef, NgZone, CORE_DIRECTIVES} from 'angular2/angular2'; 5 | 6 | // Services 7 | import {MESSAGE_PROVIDERS, Message} from '../services/Message'; 8 | 9 | import * as Rx from '@reactivex/rxjs'; 10 | 11 | interface LetterConfig { 12 | text: string; 13 | top: number; 14 | left: number; 15 | index: number; 16 | } 17 | 18 | @Component({ 19 | selector: 'timeflies', 20 | providers: [ MESSAGE_PROVIDERS ], 21 | directives: [ CORE_DIRECTIVES ], 22 | template: ` 23 |
24 | 29 | {{ letter.text }} 30 | 31 |
32 | ` 33 | }) 34 | export class Timeflies { 35 | pos = 'absolute'; 36 | color = 'red'; 37 | letters: LetterConfig[]; 38 | 39 | constructor( 40 | private service: Message, 41 | private el: ElementRef, 42 | private zone: NgZone) { 43 | 44 | } 45 | 46 | 47 | onInit() { 48 | // initial mapping (before mouse moves) 49 | this.letters = this.service.message.map( 50 | (val, idx) => ({ 51 | text: val, 52 | top: 100, 53 | left: (idx * 20 + 50), 54 | index: idx 55 | }) 56 | ); 57 | // run mouse move outside of Angular 58 | // got this hint from @mgonto 59 | this.zone.runOutsideAngular(() => { 60 | (Rx).Observable 61 | .fromEvent(this.el.nativeElement, 'mousemove') 62 | .map((e: MouseEvent) => { 63 | //var offset = getOffset(this.el); 64 | 65 | // subtract offset of the element 66 | var o = this.el.nativeElement.getBoundingClientRect(); 67 | 68 | return { 69 | offsetX: e.clientX - o.left, 70 | offsetY: e.clientY - o.top 71 | }; 72 | }) 73 | .flatMap(delta => { 74 | return (Rx).Observable 75 | .fromArray(this.letters 76 | .map((val, index) => ({ 77 | letter: val.text, 78 | delta, 79 | index 80 | }))); 81 | }) 82 | .flatMap(letterConfig => { 83 | return (Rx).Observable 84 | .timer( (letterConfig.index + 1) * 100) 85 | .map(() => ({ 86 | text: letterConfig.letter, 87 | top: letterConfig.delta.offsetY, 88 | left: letterConfig.delta.offsetX + letterConfig.index * 20 + 20, 89 | index: letterConfig.index 90 | })); 91 | }) 92 | .subscribe(letterConfig => { 93 | // to render the letters, put them back into app zone 94 | this.zone.run(() => this.letters[letterConfig.index] = letterConfig); 95 | 96 | }); 97 | });//zone 98 | }// timeflies 99 | 100 | } 101 | -------------------------------------------------------------------------------- /rx-timeflies/services/Message.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import {provide, Injectable} from 'angular2/angular2'; 3 | 4 | @Injectable() 5 | export class Message { 6 | message: Array; 7 | 8 | constructor() { 9 | this.message = ('TIME FLIES LIKE AN ARROW').split(''); 10 | } 11 | 12 | } 13 | 14 | 15 | export var MESSAGE_PROVIDERS: Array = [ 16 | provide(Message, {useClass: Message}) 17 | ]; 18 | -------------------------------------------------------------------------------- /server/db.js: -------------------------------------------------------------------------------- 1 | // your DB 2 | exports.todos = [ 3 | { value: 'finish example', created_at: new Date() }, 4 | { value: 'add tests', created_at: new Date() }, 5 | { value: 'include development environment', created_at: new Date() }, 6 | { value: 'include production environment', created_at: new Date() } 7 | ]; 8 | -------------------------------------------------------------------------------- /server/express-server-example.js: -------------------------------------------------------------------------------- 1 | // Webpack 2 | var webpack = require('webpack'); 3 | var WebpackDevServer = require('webpack-dev-server'); 4 | var webpackConfig = require('../../webpack.config'); 5 | 6 | // Express 7 | var express = require('express'); 8 | var history = require('connect-history-api-fallback'); 9 | var morgan = require('morgan'); 10 | var bodyParser = require('body-parser'); 11 | var cors = require('cors'); 12 | 13 | // Express App 14 | var app = express(); 15 | 16 | // Env 17 | var PORT = process.env.PORT || 3001; 18 | var NODE_ENV = process.env.NODE_ENV || 'development'; 19 | 20 | // Logging 21 | app.use(morgan('dev')); 22 | 23 | // Accept Content-Type 24 | app.use(bodyParser.json()); 25 | app.use(bodyParser.urlencoded({ extended: true })); 26 | 27 | // CORs 28 | var whitelist = [ 29 | 'http://localhost:8080', 30 | 'http://localhost:3001' 31 | ]; 32 | var corsOptions = { 33 | origin: true, 34 | credentials: true 35 | }; 36 | app.use(cors(corsOptionsDelegate)); 37 | 38 | // Your middleware 39 | app.use(history()); 40 | 41 | // your api middleware 42 | var api = require('./todo_api'); 43 | app.use('/api', cors(), api()); 44 | 45 | //Static files 46 | app.use(express.static('src/public')); 47 | 48 | /* 49 | // README: Uncomment only if you're not using `npm run server` 50 | // Only use in development 51 | if (NODE_ENV === 'development') { 52 | var server = new WebpackDevServer(webpack(webpackConfig), { 53 | publicPath: '/__build__', 54 | historyApiFallback: false, // won't work due to order 55 | inline: true, 56 | quiet: false, 57 | noInfo: false, 58 | stats: { colors: true } 59 | }); 60 | // Webpack express app that uses socket.io 61 | app.use(server.app); 62 | } else { 63 | app.use('/__build__', express.static('__build__')); 64 | } 65 | */ 66 | 67 | // Start the server by listening on a port 68 | app.listen(PORT, function() { 69 | console.log('Listen on http://localhost:' + PORT + ' in ' + NODE_ENV); 70 | }); 71 | 72 | 73 | // helper function to whitelist domains for cors 74 | function corsOptionsDelegate(req, callback){ 75 | var corsOpts; 76 | if (whitelist.indexOf(req.header('Origin')) !== -1) { 77 | // reflect (enable) the requested origin in the CORS response 78 | corsOpts = corsOptions; 79 | } else { 80 | // disable CORS for this request 81 | corsOpts = { origin: false }; 82 | } 83 | // callback expects two parameters: error and options 84 | callback(null, corsOpts); 85 | } 86 | -------------------------------------------------------------------------------- /server/todo_api.js: -------------------------------------------------------------------------------- 1 | // Node 2 | var util = require('util'); 3 | 4 | // Express 5 | var express = require('express'); 6 | 7 | var db = require('./db'); 8 | 9 | module.exports = function(config) { 10 | var router = express.Router(); 11 | 12 | 13 | router.route('/todos') 14 | .get(function(req, res) { 15 | console.log('GET'); 16 | res.json(db.todos); 17 | }) 18 | .post(function(req, res) { 19 | console.log('POST', util.inspect(req.body, {colors: true})); 20 | var todo = req.body; 21 | if (todo) { 22 | db.todos.push(todo); 23 | res.json(todo); 24 | } else { 25 | res.end(); 26 | } 27 | }) 28 | 29 | router.param('todo_id', function(req, res, next, todo_id) { 30 | var id = Number(req.params.todo_id); 31 | try { 32 | var todo = db.todos[id]; 33 | req.todo = db.todos[id]; 34 | next(); 35 | } catch(e) { 36 | next(new Error('failed to load todo')); 37 | } 38 | }); 39 | 40 | router.route('/todos/:todo_id') 41 | .get(function(req, res) { 42 | console.log('GET'); 43 | res.json(req.todo); 44 | }) 45 | .put(function(req, res) { 46 | console.log('PUT', util.inspect(req.body, {colors: true})); 47 | var index = db.todos.indexOf(req.todo); 48 | var todo = db.todos[index] = req.body; 49 | res.json(todo); 50 | }) 51 | .delete(function(req, res) { 52 | console.log('DELETE'); 53 | var index = db.todos.indexOf(req.todo); 54 | db.todos.splice(index, 1); 55 | res.json(req.todo); 56 | }); 57 | 58 | return router; 59 | }; 60 | -------------------------------------------------------------------------------- /simple-component/app.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component, View} from 'angular2/angular2'; 5 | 6 | import {Home} from './home/home'; 7 | 8 | /* 9 | * App Component 10 | * our top level component that holds all of our components 11 | */ 12 | @Component({ 13 | selector: 'app' 14 | }) 15 | @View({ 16 | directives: [ Home ], 17 | template: ` 18 |
19 | 20 |
21 | ` 22 | }) 23 | export class App { 24 | constructor() { 25 | 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /simple-component/bootstrap.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {bootstrap} from 'angular2/angular2'; 5 | 6 | import {FORM_BINDINGS, ELEMENT_PROBE_BINDINGS} from 'angular2/angular2' 7 | import {ROUTER_BINDINGS} from 'angular2/router'; 8 | import {HTTP_BINDINGS} from 'angular2/http'; 9 | 10 | import {App} from './app'; 11 | 12 | 13 | const APP_BINDINGS = [ 14 | // These are dependencies of our App 15 | FORM_BINDINGS, 16 | ROUTER_BINDINGS, 17 | HTTP_BINDINGS, 18 | ELEMENT_PROBE_BINDINGS 19 | ]; 20 | /* 21 | * Bootstrap our Angular app with a top level component `App` and inject 22 | * our Universal/Platform services/bindings into Angular's dependency injection 23 | */ 24 | bootstrap( 25 | // Top Level Component 26 | App, 27 | // AppBindings 28 | APP_BINDINGS 29 | ); 30 | -------------------------------------------------------------------------------- /simple-component/home/home.css: -------------------------------------------------------------------------------- 1 | .home { 2 | background-color: #F8F8F8; 3 | } 4 | -------------------------------------------------------------------------------- /simple-component/home/home.html: -------------------------------------------------------------------------------- 1 |
2 |

Home

3 |
4 | -------------------------------------------------------------------------------- /simple-component/home/home.spec.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import {Component, View} from 'angular2/angular2'; 3 | import {Home} from './home'; 4 | 5 | @Component({ 6 | selector: 'test-cmp' 7 | }) 8 | @View({ 9 | directives: [ Home ] 10 | }) 11 | class TestComponent { 12 | 13 | } 14 | 15 | describe('Home', () => { 16 | var home; 17 | 18 | beforeEach(() => { 19 | home = new Home(); 20 | }); 21 | 22 | it('should work', () => { 23 | expect(home).toBeDefined(); 24 | }); 25 | 26 | }); 27 | 28 | -------------------------------------------------------------------------------- /simple-component/home/home.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | /* 4 | * Angular 2 5 | */ 6 | import { 7 | Component, 8 | View, 9 | CORE_DIRECTIVES, 10 | FORM_DIRECTIVES 11 | } from 'angular2/angular2'; 12 | import {ROUTER_DIRECTIVES} from 'angular2/router'; 13 | 14 | // Use webpack's `require` to get files as a raw string using raw-loader 15 | let styles = require('./home.css'); 16 | let template = require('./home.html'); 17 | 18 | 19 | // Simple external file component example 20 | @Component({ 21 | selector: 'home' 22 | }) 23 | @View({ 24 | directives: [ 25 | // Angular's core directives 26 | CORE_DIRECTIVES, 27 | 28 | // Angular's form directives 29 | FORM_DIRECTIVES, 30 | 31 | // Angular's router 32 | ROUTER_DIRECTIVES, 33 | ], 34 | // include our .html and .css file 35 | styles: [ styles ], 36 | template: template 37 | }) 38 | export class Home { 39 | constructor() { 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /simple-todo/app.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component, View} from 'angular2/angular2'; 5 | 6 | import {Todo} from './components/todo'; 7 | 8 | /* 9 | * App Component 10 | * our top level component that holds all of our components 11 | */ 12 | @Component({ 13 | selector: 'app' 14 | }) 15 | @View({ 16 | directives: [ Todo ], 17 | template: ` 18 |
19 | 20 |
21 | ` 22 | }) 23 | export class App { 24 | constructor() { 25 | 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /simple-todo/bootstrap.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {bootstrap} from 'angular2/angular2'; 5 | 6 | import {FORM_BINDINGS, ELEMENT_PROBE_BINDINGS} from 'angular2/angular2' 7 | import {ROUTER_BINDINGS} from 'angular2/router'; 8 | import {HTTP_BINDINGS} from 'angular2/http'; 9 | 10 | /* 11 | * App 12 | */ 13 | import {App} from './app'; 14 | 15 | /* 16 | * Services 17 | */ 18 | import {TODO_BINDINGS} from './services/TodoService'; 19 | 20 | 21 | const APP_BINDINGS = [ 22 | // These are dependencies of our App 23 | FORM_BINDINGS, 24 | ROUTER_BINDINGS, 25 | HTTP_BINDINGS, 26 | ELEMENT_PROBE_BINDINGS, 27 | // Services 28 | TODO_BINDINGS 29 | ]; 30 | /* 31 | * Bootstrap our Angular app with a top level component `App` and inject 32 | * our Universal/Platform services/bindings into Angular's dependency injection 33 | */ 34 | bootstrap( 35 | // Top Level Component 36 | App, 37 | // AppBindings 38 | APP_BINDINGS 39 | ); 40 | -------------------------------------------------------------------------------- /simple-todo/components/todo.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | /* 4 | * Angular 2 5 | */ 6 | import { 7 | Component, 8 | View, 9 | Directive, 10 | Validators, 11 | FormBuilder, 12 | CORE_DIRECTIVES, 13 | FORM_DIRECTIVES 14 | } from 'angular2/angular2'; 15 | import {ROUTER_DIRECTIVES} from 'angular2/router'; 16 | 17 | /* 18 | * Services 19 | */ 20 | import {TodoService} from '../services/TodoService'; 21 | 22 | 23 | 24 | // Simple form component example 25 | @Component({ 26 | selector: 'todo' 27 | }) 28 | @View({ 29 | directives: [ 30 | // Angular's core directives 31 | CORE_DIRECTIVES, 32 | 33 | // Angular's form directives 34 | FORM_DIRECTIVES, 35 | 36 | // Angular's router 37 | ROUTER_DIRECTIVES, 38 | ], 39 | styles: [` 40 | .error-message { 41 | color: red; 42 | } 43 | form { 44 | padding:16px; 45 | } 46 | `], 47 | template: ` 48 | 52 | 53 | 54 | 55 | 56 | 57 | 62 | Todo is required 63 | 64 | 65 | 66 | 67 |
    68 |
  • 69 |

    70 | {{ todo.value }} 71 |
    72 | 73 | {{ todo.created_at }} 74 |

    75 |
  • 76 |
77 | ` 78 | }) 79 | export class Todo { 80 | todoForm: any; 81 | todoInput: any; 82 | state: any; 83 | constructor( 84 | public formBuilder: FormBuilder, 85 | public todoService: TodoService) { 86 | 87 | this.todoForm = formBuilder.group({ 88 | 'todo': ['', Validators.required] 89 | }); 90 | this.todoInput = this.todoForm.controls.todo; 91 | 92 | } 93 | 94 | addTodo(event, todo) { 95 | event.preventDefault(); // prevent native page refresh 96 | 97 | this.todoService.add(todo); 98 | // update the view/model 99 | this.todoInput.updateValue(''); 100 | } 101 | 102 | removeTodo(event, index) { 103 | event.preventDefault(); // prevent native page refresh 104 | 105 | this.todoService.remove(index); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /simple-todo/services/TodoService.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import {Injectable} from 'angular2/angular2'; 4 | 5 | // Our Todo Service 6 | @Injectable() 7 | export class TodoService { 8 | // we shouldn't access ._state outside of the class 9 | // our initial state defined above 10 | private _todos = [ 11 | { value: 'finish example', created_at: new Date() }, 12 | { value: 'add tests', created_at: new Date() }, 13 | { value: 'include development environment', created_at: new Date() }, 14 | { value: 'include production environment', created_at: new Date() } 15 | ]; 16 | constructor() { 17 | 18 | } 19 | 20 | cloneTodos() { 21 | return this._todos.slice(); 22 | } 23 | 24 | add(value) { 25 | // Async call to server then save state 26 | var todo = { 27 | value: value, 28 | created_at: new Date() 29 | }; 30 | 31 | var todos = this.cloneTodos(); 32 | todos.push(todo); 33 | 34 | // You can use .set to replace state 35 | this._todos = todos; 36 | } 37 | 38 | remove(index) { 39 | // Async call to server then save state 40 | 41 | var todos = this.cloneTodos(); 42 | todos.splice(index, 1); 43 | 44 | // Always Replace state 45 | this._todos = todos; 46 | 47 | } 48 | 49 | }//TodoService 50 | 51 | // export our injectables for this module 52 | export var TODO_BINDINGS: Array = [ 53 | TodoService 54 | ]; 55 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | // @AngularClass 2 | 3 | /* 4 | * Helper 5 | * env(), getBanner(), root(), and rootDir() 6 | * are defined at the bottom 7 | */ 8 | var sliceArgs = Function.prototype.call.bind(Array.prototype.slice); 9 | var toString = Function.prototype.call.bind(Object.prototype.toString); 10 | var NODE_ENV = process.env.NODE_ENV || 'development'; 11 | var pkg = require('./package.json'); 12 | 13 | // Polyfill 14 | Object.assign = require('object-assign'); 15 | 16 | // Node 17 | var path = require('path'); 18 | 19 | // NPM 20 | var webpack = require('webpack'); 21 | 22 | // Webpack Plugins 23 | var OccurenceOrderPlugin = webpack.optimize.OccurenceOrderPlugin; 24 | var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin; 25 | var UglifyJsPlugin = webpack.optimize.UglifyJsPlugin; 26 | var DedupePlugin = webpack.optimize.DedupePlugin; 27 | var DefinePlugin = webpack.DefinePlugin; 28 | var BannerPlugin = webpack.BannerPlugin; 29 | 30 | 31 | /* 32 | * Config 33 | */ 34 | module.exports = { 35 | devtool: 'source-map', 36 | debug: true, 37 | cache: true, 38 | 39 | verbose: true, 40 | displayErrorDetails: true, 41 | context: root(), 42 | stats: { 43 | colors: true, 44 | reasons: true 45 | }, 46 | 47 | // our Development Server config 48 | devServer: { 49 | inline: true, 50 | colors: true, 51 | historyApiFallback: true, 52 | contentBase: 'src/public', 53 | publicPath: '/__build__' 54 | }, 55 | 56 | // 57 | entry: { 58 | 'bootstrap-client': [ 59 | // Angular 2 Deps 60 | 'zone.js', 61 | '@reactivex/rxjs', 62 | 'reflect-metadata', 63 | // to ensure these modules are grouped together in one file 64 | 'angular2/angular2', 65 | 'angular2/core', 66 | 'angular2/router', 67 | 'angular2/http', 68 | 69 | './src/app/bootstrap-client' 70 | ], 71 | 'bootstrap-ui': [ 72 | 'zone.js', 73 | '@reactivex/rxjs', 74 | 'reflect-metadata', 75 | 76 | 'angular2/web_worker/ui', 77 | 78 | './src/app/bootstrap-ui' 79 | ], 80 | 'bootstrap-worker': [ 81 | 'zone.js', 82 | '@reactivex/rxjs', 83 | 'reflect-metadata', 84 | 85 | 'angular2/web_worker/worker', 86 | 'angular2/angular2', 87 | 'angular2/router', 88 | 'angular2/http', 89 | 90 | './src/app/bootstrap-worker' 91 | ] 92 | }, 93 | 94 | // Config for our build files 95 | output: { 96 | path: root('__build__'), 97 | filename: '[name].js', 98 | sourceMapFilename: '[name].js.map', 99 | chunkFilename: '[id].chunk.js' 100 | // publicPath: 'http://mycdn.com/' 101 | }, 102 | 103 | resolve: { 104 | root: root(), 105 | extensions: ['','.ts','.js','.json'], 106 | alias: { 107 | 'rx': '@reactivex/rxjs' 108 | // 'common': 'src/common', 109 | // 'bindings': 'src/bindings', 110 | // 'components': 'src/app/components' 111 | // 'services': 'src/app/services', 112 | // 'stores': 'src/app/stores' 113 | } 114 | }, 115 | 116 | module: { 117 | loaders: [ 118 | // Support for *.json files. 119 | { test: /\.json$/, loader: 'json' }, 120 | 121 | // Support for CSS as raw text 122 | { test: /\.css$/, loader: 'raw' }, 123 | 124 | // support for .html as raw text 125 | { test: /\.html$/, loader: 'raw' }, 126 | 127 | // Support for .ts files. 128 | { test: /\.ts$/, loader: 'ts', 129 | query: { 130 | 'ignoreDiagnostics': [ 131 | // 2300, // 2300 -> Duplicate identifier 132 | // 2309 // 2309 -> An export assignment cannot be used in a module with other exported elements. 133 | ] 134 | }, 135 | exclude: [ 136 | /\.min\.js$/, 137 | /\.spec\.ts$/, 138 | /\.e2e\.ts$/, 139 | /web_modules/, 140 | /test/, 141 | /node_modules/ 142 | ] 143 | } 144 | ], 145 | noParse: [ 146 | /rtts_assert\/src\/rtts_assert/, 147 | /reflect-metadata/ 148 | ] 149 | }, 150 | 151 | plugins: [ 152 | // new DefinePlugin({ 153 | // 'process.env.NODE_ENV': JSON.stringify(NODE_ENV), 154 | // 'VERSION': JSON.stringify(pkg.version) 155 | // }), 156 | // new OccurenceOrderPlugin(), 157 | // new DedupePlugin() 158 | ], 159 | 160 | /* 161 | * When using `templateUrl` and `styleUrls` please use `__filename` 162 | * rather than `module.id` for `moduleId` in `@View` 163 | */ 164 | node: { 165 | crypto: false, 166 | __filename: true 167 | } 168 | }; 169 | 170 | // Helper functions 171 | 172 | function env(configEnv) { 173 | if (configEnv === undefined) { return configEnv; } 174 | switch (toString(configEnv[NODE_ENV])) { 175 | case '[object Object]' : return Object.assign({}, configEnv.all || {}, configEnv[NODE_ENV]); 176 | case '[object Array]' : return [].concat(configEnv.all || [], configEnv[NODE_ENV]); 177 | case '[object Undefined]' : return configEnv.all; 178 | default : return configEnv[NODE_ENV]; 179 | } 180 | } 181 | 182 | function getBanner() { 183 | return 'Angular2 Webpack Starter v'+ pkg.version +' by @gdi2990 from @AngularClass'; 184 | } 185 | 186 | function root(args) { 187 | args = sliceArgs(arguments, 0); 188 | return path.join.apply(path, [__dirname].concat(args)); 189 | } 190 | 191 | function rootNode(args) { 192 | args = sliceArgs(arguments, 0); 193 | return root.apply(path, ['node_modules'].concat(args)); 194 | } 195 | --------------------------------------------------------------------------------