├── .editorconfig
├── .gitignore
├── README.md
├── notes.md
├── package.json
├── src
├── app.ts
├── demos
│ ├── firebase
│ │ └── firebasechat.ts
│ ├── ngrx
│ │ ├── todoapp.ts
│ │ └── todos.ts
│ └── typeahead
│ │ └── typeahead.ts
├── favicon.ico
├── index.html
└── main.ts
├── tsconfig.json
├── typings.json
└── webpack.config.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | charset = utf-8
7 | indent_style = space
8 | indent_size = 2
9 | end_of_line = lf
10 | insert_final_newline = true
11 | trim_trailing_whitespace = true
12 |
13 | [*.md]
14 | insert_final_newline = false
15 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules/
2 | /typings/
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # fluent_demos
2 | Demo code from Reactive Angular2 @ Fluent 2016. Slides [here](https://docs.google.com/presentation/d/1pBM3Is5SrXn_wmK_sF2BDXZUm44BmoUT_Ohg9da6K1k/edit?usp=sharing)
3 |
4 | ## instructions
5 |
6 | - clone this repo
7 | - `npm install`
8 | - `npm install -g typings`
9 | - `typings install`
10 | - `npm start`
11 |
--------------------------------------------------------------------------------
/notes.md:
--------------------------------------------------------------------------------
1 | const BASE_URL = 'https://www.googleapis.com/youtube/v3/search';
2 | const API_TOKEN = 'AIzaSyAJk1xUI72YYfBMgEc84gjHUX-k2AN6-B0';
3 |
4 | `${BASE_URL}?q=${query}&part=snippet&key=${API_TOKEN}`
5 |
6 |
7 |
8 |
9 |
10 |
11 | https://ngnl-chat.firebaseio.com/
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fluent-demos",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --inline --colors --display-error-details --display-cached --port 8000 --content-base src",
8 | "test": "echo \"Error: no test specified\" && exit 1",
9 | "postinstall": "typings install"
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "@ngrx/store": "1.3.3",
15 | "angular2": "2.0.0-beta.9",
16 | "angularfire2": "2.0.0-alpha.10",
17 | "es6-promise": "^3.0.2",
18 | "es6-shim": "^0.33.3",
19 | "firebase": "^2.4.0",
20 | "reflect-metadata": "^0.1.2",
21 | "rxjs": "5.0.0-beta.2",
22 | "zone.js": "^0.5.14"
23 | },
24 | "devDependencies": {
25 | "ts-loader": "^0.8.1",
26 | "typescript": "^1.7.5",
27 | "webpack": "^1.12.13",
28 | "webpack-dev-server": "^1.14.1",
29 | "webpack-livereload-plugin": "^0.5.3"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/app.ts:
--------------------------------------------------------------------------------
1 | import {Component} from 'angular2/core'
2 | import {ROUTER_PROVIDERS, ROUTER_DIRECTIVES, Router, RouteConfig} from 'angular2/router'
3 |
4 | import {TypeaheadDemo} from './demos/typeahead/typeahead.ts'
5 | import {FirebaseChat} from './demos/firebase/firebasechat.ts'
6 | import {TodoApp} from './demos/ngrx/todoapp.ts'
7 |
8 | @Component({
9 | selector: 'app',
10 | template: `
11 |
12 |
Reactive Angular2
13 |
18 |
19 |
20 | `,
21 | directives: [ROUTER_DIRECTIVES],
22 | providers: [ROUTER_PROVIDERS]
23 | })
24 | @RouteConfig([
25 | {name: 'TypeaheadDemo', component: TypeaheadDemo, path: '/typeahead', useAsDefault: true},
26 | {name: 'FirebaseChat', component: FirebaseChat, path: '/firebase'},
27 | {name: 'TodoApp', component: TodoApp, path: '/todos'},
28 | ])
29 | export class App {}
30 |
--------------------------------------------------------------------------------
/src/demos/firebase/firebasechat.ts:
--------------------------------------------------------------------------------
1 | import {Component} from 'angular2/core'
2 | import {AngularFire, defaultFirebase, FIREBASE_PROVIDERS, FirebaseListObservable} from 'angularfire2'
3 |
4 |
5 | @Component({
6 | selector: 'firebase-demo',
7 | template: `
8 | firebase demo
9 |
10 |
11 |
12 | - {{ message.text }}
13 |
14 | `,
15 | providers: [
16 | FIREBASE_PROVIDERS,
17 | defaultFirebase('https://fluent-chat-demo.firebaseio.com/')
18 | ]
19 | })
20 | export class FirebaseChat {
21 | messages: FirebaseListObservable
22 | constructor(angularFire: AngularFire){
23 | this.messages = angularFire.list('/messages');
24 | }
25 | addMessage(el){
26 |
27 | let newMessage = {text: el.value};
28 | this.messages.add(newMessage);
29 | el.value = '';
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/demos/ngrx/todoapp.ts:
--------------------------------------------------------------------------------
1 | import {Component, Injectable} from 'angular2/core'
2 | import {provideStore, Store} from '@ngrx/store'
3 | import {todos} from './todos';
4 | import {Observable} from 'rxjs/Rx'
5 |
6 | @Component({
7 | selector: 'todo-app',
8 | template: `
9 | Todos
10 |
11 |
12 | - {{todo.text}}
13 |
14 | `,
15 | providers: [provideStore({todos})]
16 | })
17 | export class TodoApp {
18 | todos: Observable;
19 | constructor(private store:Store){
20 | this.todos = store.select('todos');
21 | }
22 | addTodo(el){
23 | let text = el.value;
24 | this.store.dispatch({type: 'ADD_TODO', payload: {text}});
25 | el.value = ""
26 | }
27 | deleteTodo(todo){
28 | this.store.dispatch({type: 'DELETE_TODO', payload: todo});
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/demos/ngrx/todos.ts:
--------------------------------------------------------------------------------
1 | //todos reducer
2 |
3 | export const ADD_TODO = 'ADD_TODO';
4 | export const UPDATE_TODO = 'UPDATE_TODO';
5 | export const DELETE_TODO = 'DELETE_TODO';
6 | export const COMPLETE_TODO = 'COMPLETE_TODO';
7 |
8 | export const todos = (state = [], {type, payload}) => {
9 | switch(type){
10 | case ADD_TODO:
11 | return state.concat([Object.assign({}, payload, {id: state.length + 1})]);
12 | case UPDATE_TODO:
13 | return state.map(todo => {
14 | return todo.id !== payload.id ?
15 | todo :
16 | Object.assign({}, todo, payload)
17 | });
18 | case COMPLETE_TODO:
19 | return state.map(todo => {
20 | return todo.id !== payload.id ?
21 | todo :
22 | Object.assign({}, todo, {completed: true})
23 | });
24 | case DELETE_TODO:
25 | return state.filter(todo => todo.id !== payload.id);
26 | default:
27 | return state;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/demos/typeahead/typeahead.ts:
--------------------------------------------------------------------------------
1 | import {Component} from 'angular2/core'
2 | import {Control} from 'angular2/common'
3 | import {HTTP_PROVIDERS, Http, Response} from 'angular2/http'
4 | import 'rxjs/Rx'
5 | import {Observable} from 'rxjs/Observable'
6 |
7 | const BASE_URL = 'https://www.googleapis.com/youtube/v3/search';
8 | const API_TOKEN = 'AIzaSyAJk1xUI72YYfBMgEc84gjHUX-k2AN6-B0';
9 |
10 | const makeURL = (query) => `${BASE_URL}?q=${query}&part=snippet&key=${API_TOKEN}`
11 |
12 | @Component({
13 | selector: 'my-typeahead',
14 | template: `
15 |
16 |
17 | - {{video | json}}
18 |
19 | `
20 | })
21 | class MyTypeahead {
22 | videos: Observable;
23 | searchInput = new Control();
24 | constructor(http: Http) {
25 | this.videos = this.searchInput.valueChanges
26 | //optionally debounce
27 | //.debounceTime(300)
28 | .map(inputText => makeURL(inputText))
29 | //flatMap won't cancel in-flight requests, switchMap will...
30 | //.flatMap(url => http.get(url).map(res => res.json()))
31 | .switchMap(url => http.get(url).map(res => res.json()))
32 | .map(response => response['items']);
33 | }
34 | }
35 |
36 |
37 | @Component({
38 | selector: 'typeahead-demo',
39 | template: `
40 | typeahead demo
41 |
42 | `,
43 | providers: [HTTP_PROVIDERS],
44 | directives: [MyTypeahead]
45 | })
46 | export class TypeaheadDemo {
47 | constructor(private http: Http) { }
48 | }
49 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robwormald/fluent_demos/0eaf8fc86903188035146e53c6d7840e3e0382fc/src/favicon.ico
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | fluent demos
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata'
2 | import 'zone.js'
3 | import {bootstrap} from 'angular2/platform/browser'
4 | import {enableProdMode} from 'angular2/core'
5 | import {App} from './app'
6 |
7 | enableProdMode();
8 |
9 | bootstrap(App)
10 | .catch(console.log.bind(console));
11 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es5",
5 | "noImplicitAny": false,
6 | "sourceMap": false,
7 | "emitDecoratorMetadata": true,
8 | "experimentalDecorators": true,
9 | "suppressExcessPropertyErrors": true,
10 | "suppressImplicitAnyIndexErrors": true
11 | },
12 | "files": [
13 | "typings/browser.d.ts",
14 | "src/main.ts"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/typings.json:
--------------------------------------------------------------------------------
1 | {
2 | "ambientDependencies": {
3 | "es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#4de74cb527395c13ba20b438c3a7a419ad931f1c",
4 | "firebase": "github:DefinitelyTyped/DefinitelyTyped/firebase/firebase.d.ts#e2251a6de4ec74c4c71cbb04baccdd261a643909"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var LiveReloadPlugin = require('webpack-livereload-plugin');
2 | var webpack = require('webpack');
3 |
4 | module.exports = {
5 | resolve: {
6 | extensions: ['', '.scss', '.ts', '.js']
7 | },
8 |
9 | plugins: [
10 | new LiveReloadPlugin({
11 | appendScriptTag: true
12 | })
13 | ],
14 |
15 | entry: './src/main.ts',
16 | output: {
17 | path: "./dist",
18 | publicPath: 'dist/',
19 | filename: "bundle.js"
20 | },
21 |
22 | devtool: 'source-map',
23 |
24 | module: {
25 | loaders: [
26 | {
27 | test: /\.ts$/,
28 | loader: 'ts-loader'
29 | },
30 | {
31 | test: /\.css$/,
32 | loader: 'style-loader'
33 | }
34 | ]
35 | },
36 |
37 | devServer: {
38 | historyApiFallback: true
39 | }
40 | };
41 |
--------------------------------------------------------------------------------