SlideShare a Scribd company logo
Go Beast Mode
with Realtime
Reactive Interfaces
in Angular and Firebase
State management
Controlling flow
Code volume
Enter Observables
return this.http.get(this.URLS.FETCH)

.map(res => res.json())

.toPromise();
Problem solved!
Observables give us a powerful way to encapsulate,
transport and transform data from user interactions
to create powerful and immersive experiences.
Encapsulate
Transport
Transform
Encapsulate
Transport
Transform
Encapsulate
Transport
Transform
Iterator Pattern Observer Pattern
State Communication
Communicate
state over time
Observable stream
Values over time
SINGLE MULTIPLE
SYNCHRONOUS Function Enumerable
ASYNCHRONOUS Promise Observable
Value consumption
SINGLE MULTIPLE
PULL Function Enumerable
PUSH Promise Observable
But
observables
are hard!!!
The
Observable
Stream
input output
output input
The
Basic
Sequence
final input
initial output
magic
subscribe
event
operators
@ViewChild('btn') btn;

message: string;



ngOnInit() {

Observable.fromEvent(this.getNativeElement(this.btn), 'click')

.subscribe(result => this.message = 'Beast Mode Activated!');

}



getNativeElement(element) {

return element._elementRef.nativeElement;

}
@ViewChild('btn') btn;

message: string;



ngOnInit() {

Observable.fromEvent(this.getNativeElement(this.btn), 'click')

.subscribe(result => this.message = 'Beast Mode Activated!');

}



getNativeElement(element) {

return element._elementRef.nativeElement;

}
Initial output
@ViewChild('btn') btn;

message: string;



ngOnInit() {

Observable.fromEvent(this.getNativeElement(this.btn), 'click')

.subscribe(event => this.message = 'Beast Mode Activated!');

}



getNativeElement(element) {

return element._elementRef.nativeElement;

}
Final input
@ViewChild('btn') btn;

message: string;



ngOnInit() {

Observable.fromEvent(this.getNativeElement(this.btn), 'click')

.map(event => 'Beast Mode Activated!')

.subscribe(result => this.message = result);

}



getNativeElement(element) {

return element._elementRef.nativeElement;

}
Everything in between
@ViewChild('btn') btn;

message: string;



ngOnInit() {

Observable.fromEvent(this.getNativeElement(this.btn), 'click')

.filter(event => event.shiftKey)

.map(event => 'Beast Mode Activated!')

.subscribe(result => this.message = result);

}



getNativeElement(element) {

return element._elementRef.nativeElement;

}
Everything in between
BASIC SEQUENCE
How do we
preserve state
in a stream?
<button #right>Right</button>

<div class="container">

<div #ball class="ball"

[style.left]="position.x + 'px'"

[style.top]="position.y + 'px'">

</div>

</div>
@ViewChild('right') right;

position: any;



ngOnInit() {

Observable

.fromEvent(this.getNativeElement(this.right), 'click')

.map(event => 10)

.startWith({x: 100, y: 100})

.scan((acc, curr) => { return { y: acc.y, x: acc.x + curr}})
.subscribe(result => this.position = result);

}
@ViewChild('right') right;

position: any;



ngOnInit() {

Observable

.fromEvent(this.getNativeElement(this.right), 'click')

.map(event => 10)

.startWith({x: 100, y: 100})

.scan((acc, curr) => { return { y: acc.y, x: acc.x + curr}})

.subscribe(result => this.position = result);

}
@ViewChild('right') right;

position: any;



ngOnInit() {

Observable

.fromEvent(this.getNativeElement(this.right), 'click')

.map(event => 10)

.startWith({x: 100, y: 100})

.scan((acc, curr) => { return { y: acc.y, x: acc.x + curr}})

.subscribe(result => this.position = result);

}
@ViewChild('right') right;

position: any;



ngOnInit() {

Observable

.fromEvent(this.getNativeElement(this.right), 'click')

.map(event => 10)

.startWith({x: 100, y: 100})

.scan((acc, curr) => { return { y: acc.y, x: acc.x + curr}})

.subscribe(result => this.position = result);

}
MAINTAINING STATE
What if we have
more than one stream?
@ViewChild('left') left;

@ViewChild('right') right;

position: any;



ngOnInit() {

const left$ = Observable.fromEvent(this.getNativeElement(this.left), 'click')

.map(event => -10);



const right$ = Observable.fromEvent(this.getNativeElement(this.right), 'click')

.map(event => 10);



Observable.merge(left$, right$)

.startWith({x: 100, y: 100})

.scan((acc, curr) => { return { y: acc.y, x: acc.x + curr}})

.subscribe(result => this.position = result);

}
@ViewChild('left') left;

@ViewChild('right') right;

position: any;



ngOnInit() {

const left$ = Observable.fromEvent(this.getNativeElement(this.left), 'click')

.map(event => -10);



const right$ = Observable.fromEvent(this.getNativeElement(this.right), 'click')

.map(event => 10);



Observable.merge(left$, right$)

.startWith({x: 100, y: 100})

.scan((acc, curr) => { return { y: acc.y, x: acc.x + curr}})

.subscribe(result => this.position = result);

}
MERGING STREAMS
What can we
put in a stream?
increment(obj, prop, value) {

return Object.assign({}, obj, {[prop]: obj[prop] + value})

}



decrement(obj, prop, value) {

return Object.assign({}, obj, {[prop]: obj[prop] - value})

}



ngOnInit() {

const leftArrow$ = Observable.fromEvent(document, 'keydown')

.filter(event => event.key === 'ArrowLeft')

.mapTo(position => this.decrement(position, 'x', 10));



const rightArrow$ = Observable.fromEvent(document, 'keydown')

.filter(event => event.key === 'ArrowRight')

.mapTo(position => this.increment(position, 'x', 10));



Observable.merge(leftArrow$, rightArrow$)

.startWith({x: 100, y: 100})

.scan((acc, curr) => curr(acc))

.subscribe(result => this.position = result);

}
increment(obj, prop, value) {

return Object.assign({}, obj, {[prop]: obj[prop] + value})

}



decrement(obj, prop, value) {

return Object.assign({}, obj, {[prop]: obj[prop] - value})

}



ngOnInit() {

const leftArrow$ = Observable.fromEvent(document, 'keydown')

.filter(event => event.key === 'ArrowLeft')

.mapTo(position => this.decrement(position, 'x', 10));



const rightArrow$ = Observable.fromEvent(document, 'keydown')

.filter(event => event.key === 'ArrowRight')

.mapTo(position => this.increment(position, 'x', 10));



Observable.merge(leftArrow$, rightArrow$)

.startWith({x: 100, y: 100})

.scan((acc, curr) => curr(acc))

.subscribe(result => this.position = result);

}
increment(obj, prop, value) {

return Object.assign({}, obj, {[prop]: obj[prop] + value})

}



decrement(obj, prop, value) {

return Object.assign({}, obj, {[prop]: obj[prop] - value})

}



ngOnInit() {

const leftArrow$ = Observable.fromEvent(document, 'keydown')

.filter(event => event.key === 'ArrowLeft')

.mapTo(position => this.decrement(position, 'x', 10));



const rightArrow$ = Observable.fromEvent(document, 'keydown')

.filter(event => event.key === 'ArrowRight')

.mapTo(position => this.increment(position, 'x', 10));



Observable.merge(leftArrow$, rightArrow$)

.startWith({x: 100, y: 100})

.scan((acc, curr) => curr(acc))

.subscribe(result => this.position = result);

}
MAPPING TO FUNCTIONS
How can we
sequence a stream?
@ViewChild('ball') ball;

position: any;



ngOnInit() {

const OFFSET = 50;

const move$ = Observable.fromEvent(document, 'mousemove')

.map(event => {

return {x: event.pageX - OFFSET, y: event.pageY - OFFSET};

});



const down$ = Observable.fromEvent(this.ball.nativeElement, 'mousedown');



down$

.switchMap(event => move$)

.startWith({ x: 100, y: 100})

.subscribe(result => this.position = result);

}
@ViewChild('ball') ball;

position: any;



ngOnInit() {

const OFFSET = 50;

const move$ = Observable.fromEvent(document, 'mousemove')

.map(event => {

return {x: event.pageX - OFFSET, y: event.pageY - OFFSET};

});



const down$ = Observable.fromEvent(this.ball.nativeElement, 'mousedown');



down$

.switchMap(event => move$)

.startWith({ x: 100, y: 100})

.subscribe(result => this.position = result);

}
@ViewChild('ball') ball;

position: any;



ngOnInit() {

const OFFSET = 50;

const move$ = Observable.fromEvent(document, 'mousemove')

.map(event => {

return {x: event.pageX - OFFSET, y: event.pageY - OFFSET};

});



const down$ = Observable.fromEvent(this.ball.nativeElement, 'mousedown');



down$

.switchMap(event => move$)


.startWith({ x: 100, y: 100})
.subscribe(result => this.position = result);

}
@ViewChild('ball') ball;

position: any;



ngOnInit() {

const OFFSET = 50;

const move$ = Observable.fromEvent(document, 'mousemove')

.map(event => {

return {x: event.pageX - OFFSET, y: event.pageY - OFFSET};

});



const down$ = Observable.fromEvent(this.ball.nativeElement, 'mousedown');



down$

.switchMap(event => move$)


.startWith({ x: 100, y: 100})
.subscribe(result => this.position = result);

}
@ViewChild('ball') ball;

position: any;



ngOnInit() {

const OFFSET = 50;

const move$ = Observable.fromEvent(document, 'mousemove')

.map(event => {

return {x: event.pageX - OFFSET, y: event.pageY - OFFSET};

});



const down$ = Observable.fromEvent(this.ball.nativeElement, 'mousedown');

const up$ = Observable.fromEvent(document, 'mouseup');



down$

.switchMap(event => move$.takeUntil(up$))

.startWith({ x: 100, y: 100})

.subscribe(result => this.position = result);

}
TRIGGERS
What effect does the
origin of the stream
have on the output?
<div class="container">

<app-line

*ngFor="let line of lines" [line]="line">

</app-line>

</div>
<svg>

<line [attr.x1]="line.x1" [attr.y1]="line.y1"

[attr.x2]="line.x2" [attr.y2]="line.y2"

style="stroke:rgb(255,0,0);stroke-width:2"/>

</svg>
lines: any[] = [];

ngOnInit() {

Observable.fromEvent(document, 'click')

.map(event => {

return {x: event.pageX, y: event.pageY};

})

.pairwise(2)

.map(positions => {

const p1 = positions[0];

const p2 = positions[1];

return { x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y };

})

.subscribe(line => this.lines = [...this.lines, line]);

}
STREAM ORIGINS
lines: any[] = [];

ngOnInit() {

Observable.fromEvent(document, 'mousemove')

.map(event => {

return {x: event.pageX, y: event.pageY};

})

.pairwise(2)

.map(position => {

const p1 = positions[0];

const p2 = positions[1];

return { x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y };

})

.subscribe(line => this.lines = [...this.lines, line]);

}
STREAM ORIGINS
What are some fun
things we can do with
a stream?
@ViewChild('ball') ball;

ngOnInit() {

const OFFSET = 50;



Observable.fromEvent(document, 'click')

.map(event => {

return {x: event.clientX - OFFSET, y: event.clientY - OFFSET}

})

.subscribe(props => TweenMax.to(this.ball.nativeElement, 1, props))

}
SIMPLE ANIMATION
What are some MOAR
fun things we can do
with a stream?
circles: any[] = [];

ngOnInit() {

const OFFSET = 25;


Observable.fromEvent(document, 'mousemove')

.map(event => {

return { x: event.clientX - OFFSET, y: event.clientY - OFFSET}

})

.subscribe(circle => this.circles = [ ...this.circles, circle])

}
<div class="container">

<app-circle

*ngFor="let circle of circles"

[style.left]="circle.x + 'px'"

[style.top]="circle.y + 'px'">

</app-circle>

</div>
export class CircleComponent implements OnInit {

@ViewChild('circle') circle;



ngOnInit() {

TweenMax.to(this.circle.nativeElement, 2, 

{alpha: 0, width: 0, height: 0});

}

}
ANIMATION
The
Realtime
Observable
Stream
Start with a
realtime database
You
called?
import { AngularFireModule } from 'angularfire2';
export const firebaseConfig = {

apiKey: 'PETERBACONDARWINISABEASTINSHEEPSCLOTHING',

authDomain: 'rxjsbeastmode.firebaseapp.com',

databaseURL: 'https://rxjsbeastmode.firebaseio.com',

storageBucket: ''

};

@NgModule({

declarations: [AppComponent],

imports: [

BrowserModule,

AngularFireModule.initializeApp(firebaseConfig),

],

bootstrap: [AppComponent]

})

export class AppModule {}
import { AngularFireModule } from 'angularfire2';
export const firebaseConfig = {

apiKey: 'PETERBACONDARWINISABEASTINSHEEPSCLOTHING',

authDomain: 'rxjsbeastmode.firebaseapp.com',

databaseURL: 'https://rxjsbeastmode.firebaseio.com',

storageBucket: ''

};

@NgModule({

declarations: [AppComponent],

imports: [

BrowserModule,

AngularFireModule.initializeApp(firebaseConfig),

],

bootstrap: [AppComponent]

})

export class AppModule {}
Consume the
realtime stream
const remote$ = this.af.database.object('clicker/');



remote$

.subscribe(result => this.count = result.ticker);
Update the
realtime stream
const remote$ = this.af.database.object('clicker/');



Observable.fromEvent(this.getNativeElement(this.btn), 'click')

.startWith({ticker: 0})

.scan((acc, curr) => { return { ticker: acc.ticker + 1 }; })

.subscribe(event => remote$.update(event));
const remote$ = this.af.database.object('clicker/');

// Outgoing

Observable.fromEvent(this.getNativeElement(this.btn), 'click')

.startWith({ticker: 0})

.scan((acc, curr) => { return { ticker: acc.ticker + 1 }; })

.subscribe(event => remote$.update(event));

// Incoming

remote$

.subscribe(result => this.message = result.message);
const remote$ = this.af.database.object('clicker/');

// Outgoing ——>

Observable.fromEvent(this.getNativeElement(this.btn), 'click')

.startWith({ticker: 0})

.scan((acc, curr) => { return { ticker: acc.ticker + 1 }; })

.subscribe(event => remote$.update(event));

// <—— Incoming

remote$

.subscribe(result => this.message = result.message);
BEAST MODE TIME!
REALTIME COUNTER
REALTIME SLIDESHOW
REALTIME LOCATION
REALTIME MAP
REALTIME ANNOTATIONS
REALTIME GAME
BUSINESS MODE TIME!
REALTIME SLIDER
But
observables
are hard!!!
I YOU!
@simpulton
https://egghead.io/courses/step-by-step-async-javascript-with-rxjs
https://egghead.io/courses/introduction-to-reactive-programming
Thanks!

More Related Content

What's hot

Universal JavaScript
Universal JavaScriptUniversal JavaScript
Universal JavaScript
名辰 洪
 
The redux saga begins
The redux saga beginsThe redux saga begins
The redux saga begins
Daniel Franz
 
google play service 7.8 & new tech in M
google play service 7.8 & new tech in M google play service 7.8 & new tech in M
google play service 7.8 & new tech in M
Ted Liang
 
The Ring programming language version 1.8 book - Part 65 of 202
The Ring programming language version 1.8 book - Part 65 of 202The Ring programming language version 1.8 book - Part 65 of 202
The Ring programming language version 1.8 book - Part 65 of 202
Mahmoud Samir Fayed
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
Ignacio Martín
 
Higher-Order Components — Ilya Gelman
Higher-Order Components — Ilya GelmanHigher-Order Components — Ilya Gelman
Higher-Order Components — Ilya Gelman
500Tech
 
The evolution of redux action creators
The evolution of redux action creatorsThe evolution of redux action creators
The evolution of redux action creators
George Bukhanov
 
Java awt
Java awtJava awt
rx.js make async programming simpler
rx.js make async programming simplerrx.js make async programming simpler
rx.js make async programming simpler
Alexander Mostovenko
 
Clojure functions examples
Clojure functions examplesClojure functions examples
Clojure functions examples
Jackson dos Santos Olveira
 
AngularJS, More Than Directives !
AngularJS, More Than Directives !AngularJS, More Than Directives !
AngularJS, More Than Directives !
Gaurav Behere
 
The Ring programming language version 1.6 book - Part 68 of 189
The Ring programming language version 1.6 book - Part 68 of 189The Ring programming language version 1.6 book - Part 68 of 189
The Ring programming language version 1.6 book - Part 68 of 189
Mahmoud Samir Fayed
 
Using Redux-Saga for Handling Side Effects
Using Redux-Saga for Handling Side EffectsUsing Redux-Saga for Handling Side Effects
Using Redux-Saga for Handling Side Effects
GlobalLogic Ukraine
 
Tweaking the interactive grid
Tweaking the interactive gridTweaking the interactive grid
Tweaking the interactive grid
Roel Hartman
 
Actividad #7 codigo detección de errores (yango colmenares)
Actividad #7 codigo detección de errores (yango colmenares)Actividad #7 codigo detección de errores (yango colmenares)
Actividad #7 codigo detección de errores (yango colmenares)
Yango Alexander Colmenares
 
The Ring programming language version 1.5.1 book - Part 62 of 180
The Ring programming language version 1.5.1 book - Part 62 of 180The Ring programming language version 1.5.1 book - Part 62 of 180
The Ring programming language version 1.5.1 book - Part 62 of 180
Mahmoud Samir Fayed
 
Reactive programming with RxJS - ByteConf 2018
Reactive programming with RxJS - ByteConf 2018Reactive programming with RxJS - ByteConf 2018
Reactive programming with RxJS - ByteConf 2018
Tracy Lee
 
Bindings: the zen of montage
Bindings: the zen of montageBindings: the zen of montage
Bindings: the zen of montage
Kris Kowal
 
Model View Intent on Android
Model View Intent on AndroidModel View Intent on Android
Model View Intent on Android
Cody Engel
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
Ignacio Martín
 

What's hot (20)

Universal JavaScript
Universal JavaScriptUniversal JavaScript
Universal JavaScript
 
The redux saga begins
The redux saga beginsThe redux saga begins
The redux saga begins
 
google play service 7.8 & new tech in M
google play service 7.8 & new tech in M google play service 7.8 & new tech in M
google play service 7.8 & new tech in M
 
The Ring programming language version 1.8 book - Part 65 of 202
The Ring programming language version 1.8 book - Part 65 of 202The Ring programming language version 1.8 book - Part 65 of 202
The Ring programming language version 1.8 book - Part 65 of 202
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
 
Higher-Order Components — Ilya Gelman
Higher-Order Components — Ilya GelmanHigher-Order Components — Ilya Gelman
Higher-Order Components — Ilya Gelman
 
The evolution of redux action creators
The evolution of redux action creatorsThe evolution of redux action creators
The evolution of redux action creators
 
Java awt
Java awtJava awt
Java awt
 
rx.js make async programming simpler
rx.js make async programming simplerrx.js make async programming simpler
rx.js make async programming simpler
 
Clojure functions examples
Clojure functions examplesClojure functions examples
Clojure functions examples
 
AngularJS, More Than Directives !
AngularJS, More Than Directives !AngularJS, More Than Directives !
AngularJS, More Than Directives !
 
The Ring programming language version 1.6 book - Part 68 of 189
The Ring programming language version 1.6 book - Part 68 of 189The Ring programming language version 1.6 book - Part 68 of 189
The Ring programming language version 1.6 book - Part 68 of 189
 
Using Redux-Saga for Handling Side Effects
Using Redux-Saga for Handling Side EffectsUsing Redux-Saga for Handling Side Effects
Using Redux-Saga for Handling Side Effects
 
Tweaking the interactive grid
Tweaking the interactive gridTweaking the interactive grid
Tweaking the interactive grid
 
Actividad #7 codigo detección de errores (yango colmenares)
Actividad #7 codigo detección de errores (yango colmenares)Actividad #7 codigo detección de errores (yango colmenares)
Actividad #7 codigo detección de errores (yango colmenares)
 
The Ring programming language version 1.5.1 book - Part 62 of 180
The Ring programming language version 1.5.1 book - Part 62 of 180The Ring programming language version 1.5.1 book - Part 62 of 180
The Ring programming language version 1.5.1 book - Part 62 of 180
 
Reactive programming with RxJS - ByteConf 2018
Reactive programming with RxJS - ByteConf 2018Reactive programming with RxJS - ByteConf 2018
Reactive programming with RxJS - ByteConf 2018
 
Bindings: the zen of montage
Bindings: the zen of montageBindings: the zen of montage
Bindings: the zen of montage
 
Model View Intent on Android
Model View Intent on AndroidModel View Intent on Android
Model View Intent on Android
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
 

Viewers also liked

Get that Corner Office with Angular 2 and Electron
Get that Corner Office with Angular 2 and ElectronGet that Corner Office with Angular 2 and Electron
Get that Corner Office with Angular 2 and Electron
Lukas Ruebbelke
 
Embrace the Angular 2 Ethos in Angular 1.x
Embrace the Angular 2 Ethos in Angular 1.xEmbrace the Angular 2 Ethos in Angular 1.x
Embrace the Angular 2 Ethos in Angular 1.x
Lukas Ruebbelke
 
Turn Your Designers Into Death Stars with Angular
Turn Your Designers Into Death Stars with AngularTurn Your Designers Into Death Stars with Angular
Turn Your Designers Into Death Stars with Angular
Lukas Ruebbelke
 
The REAL Angular Keynote
The REAL Angular KeynoteThe REAL Angular Keynote
The REAL Angular Keynote
Lukas Ruebbelke
 
Badges? We don't need no stinkin' badges!
Badges? We don't need no stinkin' badges!Badges? We don't need no stinkin' badges!
Badges? We don't need no stinkin' badges!
Lukas Ruebbelke
 
AngularJS Directives - DSL for your HTML
AngularJS Directives - DSL for your HTMLAngularJS Directives - DSL for your HTML
AngularJS Directives - DSL for your HTML
Lukas Ruebbelke
 
ngEurope 2014: Become a Realtime Cage Dragon with Firebase and AngularJS
ngEurope 2014: Become a Realtime Cage Dragon with Firebase and AngularJSngEurope 2014: Become a Realtime Cage Dragon with Firebase and AngularJS
ngEurope 2014: Become a Realtime Cage Dragon with Firebase and AngularJS
Lukas Ruebbelke
 
ngAnimate crash course
ngAnimate crash coursengAnimate crash course
ngAnimate crash course
Lukas Ruebbelke
 
Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015
Lukas Ruebbelke
 
RxJS - The Reactive extensions for JavaScript
RxJS - The Reactive extensions for JavaScriptRxJS - The Reactive extensions for JavaScript
RxJS - The Reactive extensions for JavaScript
Viliam Elischer
 
Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)
Eyal Vardi
 
Ionic Crash Course! Hack-a-ton SF
Ionic Crash Course! Hack-a-ton SFIonic Crash Course! Hack-a-ton SF
Ionic Crash Course! Hack-a-ton SF
Lukas Ruebbelke
 
Summer internship report | repairwale.com mobile application design and devel...
Summer internship report | repairwale.com mobile application design and devel...Summer internship report | repairwale.com mobile application design and devel...
Summer internship report | repairwale.com mobile application design and devel...
Rajath Thomson
 

Viewers also liked (13)

Get that Corner Office with Angular 2 and Electron
Get that Corner Office with Angular 2 and ElectronGet that Corner Office with Angular 2 and Electron
Get that Corner Office with Angular 2 and Electron
 
Embrace the Angular 2 Ethos in Angular 1.x
Embrace the Angular 2 Ethos in Angular 1.xEmbrace the Angular 2 Ethos in Angular 1.x
Embrace the Angular 2 Ethos in Angular 1.x
 
Turn Your Designers Into Death Stars with Angular
Turn Your Designers Into Death Stars with AngularTurn Your Designers Into Death Stars with Angular
Turn Your Designers Into Death Stars with Angular
 
The REAL Angular Keynote
The REAL Angular KeynoteThe REAL Angular Keynote
The REAL Angular Keynote
 
Badges? We don't need no stinkin' badges!
Badges? We don't need no stinkin' badges!Badges? We don't need no stinkin' badges!
Badges? We don't need no stinkin' badges!
 
AngularJS Directives - DSL for your HTML
AngularJS Directives - DSL for your HTMLAngularJS Directives - DSL for your HTML
AngularJS Directives - DSL for your HTML
 
ngEurope 2014: Become a Realtime Cage Dragon with Firebase and AngularJS
ngEurope 2014: Become a Realtime Cage Dragon with Firebase and AngularJSngEurope 2014: Become a Realtime Cage Dragon with Firebase and AngularJS
ngEurope 2014: Become a Realtime Cage Dragon with Firebase and AngularJS
 
ngAnimate crash course
ngAnimate crash coursengAnimate crash course
ngAnimate crash course
 
Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015
 
RxJS - The Reactive extensions for JavaScript
RxJS - The Reactive extensions for JavaScriptRxJS - The Reactive extensions for JavaScript
RxJS - The Reactive extensions for JavaScript
 
Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)
 
Ionic Crash Course! Hack-a-ton SF
Ionic Crash Course! Hack-a-ton SFIonic Crash Course! Hack-a-ton SF
Ionic Crash Course! Hack-a-ton SF
 
Summer internship report | repairwale.com mobile application design and devel...
Summer internship report | repairwale.com mobile application design and devel...Summer internship report | repairwale.com mobile application design and devel...
Summer internship report | repairwale.com mobile application design and devel...
 

Similar to Go Beast Mode with Realtime Reactive Interfaces in Angular 2 and Firebase

You will learn RxJS in 2017
You will learn RxJS in 2017You will learn RxJS in 2017
You will learn RxJS in 2017
名辰 洪
 
RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術
名辰 洪
 
KODE JS POKENNNNN
KODE JS POKENNNNNKODE JS POKENNNNN
KODE JS POKENNNNN
Pipo Atem
 
Cyclejs introduction
Cyclejs introductionCyclejs introduction
Cyclejs introduction
Arye Lukashevski
 
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
GeeksLab Odessa
 
Let it Flow - Introduction to Functional Reactive Programming
Let it Flow - Introduction to Functional Reactive ProgrammingLet it Flow - Introduction to Functional Reactive Programming
Let it Flow - Introduction to Functional Reactive Programming
Artur Skowroński
 
Rxjs ngvikings
Rxjs ngvikingsRxjs ngvikings
Rxjs ngvikings
Christoffer Noring
 
bacon.js
bacon.jsbacon.js
Create a java project that - Draw a circle with three random init.pdf
Create a java project that - Draw a circle with three random init.pdfCreate a java project that - Draw a circle with three random init.pdf
Create a java project that - Draw a circle with three random init.pdf
arihantmobileselepun
 
Modern JavaScript Engine Performance
Modern JavaScript Engine PerformanceModern JavaScript Engine Performance
Modern JavaScript Engine Performance
Catalin Dumitru
 
Effector: we need to go deeper
Effector: we need to go deeperEffector: we need to go deeper
Effector: we need to go deeper
Victor Didenko
 
Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016
Ben Lesh
 
package chapter15;import javafx.application.Application;import j.pdf
package chapter15;import javafx.application.Application;import j.pdfpackage chapter15;import javafx.application.Application;import j.pdf
package chapter15;import javafx.application.Application;import j.pdf
KARTIKINDIA
 
Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.
Astrails
 
React 101
React 101React 101
React 101
Casear Chu
 
React.js: Beyond the Browser
React.js: Beyond the BrowserReact.js: Beyond the Browser
React.js: Beyond the Browser
garbles
 
Ruby-ying Javascript: Avoiding jQuery Spaghetti
Ruby-ying Javascript: Avoiding jQuery SpaghettiRuby-ying Javascript: Avoiding jQuery Spaghetti
Ruby-ying Javascript: Avoiding jQuery Spaghetti
Forrest Chang
 
srcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docx
srcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docxsrcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docx
srcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docx
whitneyleman54422
 
04 Advanced Javascript
04 Advanced Javascript04 Advanced Javascript
04 Advanced Javascript
crgwbr
 
Creating an Uber Clone - Part XVIII - Transcript.pdf
Creating an Uber Clone - Part XVIII - Transcript.pdfCreating an Uber Clone - Part XVIII - Transcript.pdf
Creating an Uber Clone - Part XVIII - Transcript.pdf
ShaiAlmog1
 

Similar to Go Beast Mode with Realtime Reactive Interfaces in Angular 2 and Firebase (20)

You will learn RxJS in 2017
You will learn RxJS in 2017You will learn RxJS in 2017
You will learn RxJS in 2017
 
RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術
 
KODE JS POKENNNNN
KODE JS POKENNNNNKODE JS POKENNNNN
KODE JS POKENNNNN
 
Cyclejs introduction
Cyclejs introductionCyclejs introduction
Cyclejs introduction
 
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
 
Let it Flow - Introduction to Functional Reactive Programming
Let it Flow - Introduction to Functional Reactive ProgrammingLet it Flow - Introduction to Functional Reactive Programming
Let it Flow - Introduction to Functional Reactive Programming
 
Rxjs ngvikings
Rxjs ngvikingsRxjs ngvikings
Rxjs ngvikings
 
bacon.js
bacon.jsbacon.js
bacon.js
 
Create a java project that - Draw a circle with three random init.pdf
Create a java project that - Draw a circle with three random init.pdfCreate a java project that - Draw a circle with three random init.pdf
Create a java project that - Draw a circle with three random init.pdf
 
Modern JavaScript Engine Performance
Modern JavaScript Engine PerformanceModern JavaScript Engine Performance
Modern JavaScript Engine Performance
 
Effector: we need to go deeper
Effector: we need to go deeperEffector: we need to go deeper
Effector: we need to go deeper
 
Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016
 
package chapter15;import javafx.application.Application;import j.pdf
package chapter15;import javafx.application.Application;import j.pdfpackage chapter15;import javafx.application.Application;import j.pdf
package chapter15;import javafx.application.Application;import j.pdf
 
Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.
 
React 101
React 101React 101
React 101
 
React.js: Beyond the Browser
React.js: Beyond the BrowserReact.js: Beyond the Browser
React.js: Beyond the Browser
 
Ruby-ying Javascript: Avoiding jQuery Spaghetti
Ruby-ying Javascript: Avoiding jQuery SpaghettiRuby-ying Javascript: Avoiding jQuery Spaghetti
Ruby-ying Javascript: Avoiding jQuery Spaghetti
 
srcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docx
srcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docxsrcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docx
srcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docx
 
04 Advanced Javascript
04 Advanced Javascript04 Advanced Javascript
04 Advanced Javascript
 
Creating an Uber Clone - Part XVIII - Transcript.pdf
Creating an Uber Clone - Part XVIII - Transcript.pdfCreating an Uber Clone - Part XVIII - Transcript.pdf
Creating an Uber Clone - Part XVIII - Transcript.pdf
 

Recently uploaded

Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Jeffrey Haguewood
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
Daiki Mogmet Ito
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Safe Software
 
UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
DianaGray10
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
Chart Kalyan
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
Octavian Nadolu
 
OpenID AuthZEN Interop Read Out - Authorization
OpenID AuthZEN Interop Read Out - AuthorizationOpenID AuthZEN Interop Read Out - Authorization
OpenID AuthZEN Interop Read Out - Authorization
David Brossard
 
Webinar: Designing a schema for a Data Warehouse
Webinar: Designing a schema for a Data WarehouseWebinar: Designing a schema for a Data Warehouse
Webinar: Designing a schema for a Data Warehouse
Federico Razzoli
 
Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
Zilliz
 
Digital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying AheadDigital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying Ahead
Wask
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
danishmna97
 
Best 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERPBest 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERP
Pixlogix Infotech
 
Mariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceXMariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceX
Mariano Tinti
 
Serial Arm Control in Real Time Presentation
Serial Arm Control in Real Time PresentationSerial Arm Control in Real Time Presentation
Serial Arm Control in Real Time Presentation
tolgahangng
 
Programming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup SlidesProgramming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup Slides
Zilliz
 
GraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracyGraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracy
Tomaz Bratanic
 
WeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation TechniquesWeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation Techniques
Postman
 
Skybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoptionSkybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoption
Tatiana Kojar
 
Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024
Jason Packer
 
UI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentationUI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentation
Wouter Lemaire
 

Recently uploaded (20)

Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
 
UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
 
OpenID AuthZEN Interop Read Out - Authorization
OpenID AuthZEN Interop Read Out - AuthorizationOpenID AuthZEN Interop Read Out - Authorization
OpenID AuthZEN Interop Read Out - Authorization
 
Webinar: Designing a schema for a Data Warehouse
Webinar: Designing a schema for a Data WarehouseWebinar: Designing a schema for a Data Warehouse
Webinar: Designing a schema for a Data Warehouse
 
Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
 
Digital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying AheadDigital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying Ahead
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
 
Best 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERPBest 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERP
 
Mariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceXMariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceX
 
Serial Arm Control in Real Time Presentation
Serial Arm Control in Real Time PresentationSerial Arm Control in Real Time Presentation
Serial Arm Control in Real Time Presentation
 
Programming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup SlidesProgramming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup Slides
 
GraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracyGraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracy
 
WeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation TechniquesWeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation Techniques
 
Skybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoptionSkybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoption
 
Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024
 
UI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentationUI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentation
 

Go Beast Mode with Realtime Reactive Interfaces in Angular 2 and Firebase

  • 1. Go Beast Mode with Realtime Reactive Interfaces in Angular and Firebase
  • 6. return this.http.get(this.URLS.FETCH)
 .map(res => res.json())
 .toPromise(); Problem solved!
  • 7. Observables give us a powerful way to encapsulate, transport and transform data from user interactions to create powerful and immersive experiences.
  • 11. Iterator Pattern Observer Pattern State Communication
  • 14. Values over time SINGLE MULTIPLE SYNCHRONOUS Function Enumerable ASYNCHRONOUS Promise Observable
  • 15. Value consumption SINGLE MULTIPLE PULL Function Enumerable PUSH Promise Observable
  • 23. @ViewChild('btn') btn;
 message: string;
 
 ngOnInit() {
 Observable.fromEvent(this.getNativeElement(this.btn), 'click')
 .subscribe(result => this.message = 'Beast Mode Activated!');
 }
 
 getNativeElement(element) {
 return element._elementRef.nativeElement;
 }
  • 24. @ViewChild('btn') btn;
 message: string;
 
 ngOnInit() {
 Observable.fromEvent(this.getNativeElement(this.btn), 'click')
 .subscribe(result => this.message = 'Beast Mode Activated!');
 }
 
 getNativeElement(element) {
 return element._elementRef.nativeElement;
 } Initial output
  • 25. @ViewChild('btn') btn;
 message: string;
 
 ngOnInit() {
 Observable.fromEvent(this.getNativeElement(this.btn), 'click')
 .subscribe(event => this.message = 'Beast Mode Activated!');
 }
 
 getNativeElement(element) {
 return element._elementRef.nativeElement;
 } Final input
  • 26. @ViewChild('btn') btn;
 message: string;
 
 ngOnInit() {
 Observable.fromEvent(this.getNativeElement(this.btn), 'click')
 .map(event => 'Beast Mode Activated!')
 .subscribe(result => this.message = result);
 }
 
 getNativeElement(element) {
 return element._elementRef.nativeElement;
 } Everything in between
  • 27. @ViewChild('btn') btn;
 message: string;
 
 ngOnInit() {
 Observable.fromEvent(this.getNativeElement(this.btn), 'click')
 .filter(event => event.shiftKey)
 .map(event => 'Beast Mode Activated!')
 .subscribe(result => this.message = result);
 }
 
 getNativeElement(element) {
 return element._elementRef.nativeElement;
 } Everything in between
  • 29. How do we preserve state in a stream?
  • 30. <button #right>Right</button>
 <div class="container">
 <div #ball class="ball"
 [style.left]="position.x + 'px'"
 [style.top]="position.y + 'px'">
 </div>
 </div>
  • 31. @ViewChild('right') right;
 position: any;
 
 ngOnInit() {
 Observable
 .fromEvent(this.getNativeElement(this.right), 'click')
 .map(event => 10)
 .startWith({x: 100, y: 100})
 .scan((acc, curr) => { return { y: acc.y, x: acc.x + curr}}) .subscribe(result => this.position = result);
 }
  • 32. @ViewChild('right') right;
 position: any;
 
 ngOnInit() {
 Observable
 .fromEvent(this.getNativeElement(this.right), 'click')
 .map(event => 10)
 .startWith({x: 100, y: 100})
 .scan((acc, curr) => { return { y: acc.y, x: acc.x + curr}})
 .subscribe(result => this.position = result);
 }
  • 33. @ViewChild('right') right;
 position: any;
 
 ngOnInit() {
 Observable
 .fromEvent(this.getNativeElement(this.right), 'click')
 .map(event => 10)
 .startWith({x: 100, y: 100})
 .scan((acc, curr) => { return { y: acc.y, x: acc.x + curr}})
 .subscribe(result => this.position = result);
 }
  • 34. @ViewChild('right') right;
 position: any;
 
 ngOnInit() {
 Observable
 .fromEvent(this.getNativeElement(this.right), 'click')
 .map(event => 10)
 .startWith({x: 100, y: 100})
 .scan((acc, curr) => { return { y: acc.y, x: acc.x + curr}})
 .subscribe(result => this.position = result);
 }
  • 36. What if we have more than one stream?
  • 37. @ViewChild('left') left;
 @ViewChild('right') right;
 position: any;
 
 ngOnInit() {
 const left$ = Observable.fromEvent(this.getNativeElement(this.left), 'click')
 .map(event => -10);
 
 const right$ = Observable.fromEvent(this.getNativeElement(this.right), 'click')
 .map(event => 10);
 
 Observable.merge(left$, right$)
 .startWith({x: 100, y: 100})
 .scan((acc, curr) => { return { y: acc.y, x: acc.x + curr}})
 .subscribe(result => this.position = result);
 }
  • 38. @ViewChild('left') left;
 @ViewChild('right') right;
 position: any;
 
 ngOnInit() {
 const left$ = Observable.fromEvent(this.getNativeElement(this.left), 'click')
 .map(event => -10);
 
 const right$ = Observable.fromEvent(this.getNativeElement(this.right), 'click')
 .map(event => 10);
 
 Observable.merge(left$, right$)
 .startWith({x: 100, y: 100})
 .scan((acc, curr) => { return { y: acc.y, x: acc.x + curr}})
 .subscribe(result => this.position = result);
 }
  • 40. What can we put in a stream?
  • 41. increment(obj, prop, value) {
 return Object.assign({}, obj, {[prop]: obj[prop] + value})
 }
 
 decrement(obj, prop, value) {
 return Object.assign({}, obj, {[prop]: obj[prop] - value})
 }
 
 ngOnInit() {
 const leftArrow$ = Observable.fromEvent(document, 'keydown')
 .filter(event => event.key === 'ArrowLeft')
 .mapTo(position => this.decrement(position, 'x', 10));
 
 const rightArrow$ = Observable.fromEvent(document, 'keydown')
 .filter(event => event.key === 'ArrowRight')
 .mapTo(position => this.increment(position, 'x', 10));
 
 Observable.merge(leftArrow$, rightArrow$)
 .startWith({x: 100, y: 100})
 .scan((acc, curr) => curr(acc))
 .subscribe(result => this.position = result);
 }
  • 42. increment(obj, prop, value) {
 return Object.assign({}, obj, {[prop]: obj[prop] + value})
 }
 
 decrement(obj, prop, value) {
 return Object.assign({}, obj, {[prop]: obj[prop] - value})
 }
 
 ngOnInit() {
 const leftArrow$ = Observable.fromEvent(document, 'keydown')
 .filter(event => event.key === 'ArrowLeft')
 .mapTo(position => this.decrement(position, 'x', 10));
 
 const rightArrow$ = Observable.fromEvent(document, 'keydown')
 .filter(event => event.key === 'ArrowRight')
 .mapTo(position => this.increment(position, 'x', 10));
 
 Observable.merge(leftArrow$, rightArrow$)
 .startWith({x: 100, y: 100})
 .scan((acc, curr) => curr(acc))
 .subscribe(result => this.position = result);
 }
  • 43. increment(obj, prop, value) {
 return Object.assign({}, obj, {[prop]: obj[prop] + value})
 }
 
 decrement(obj, prop, value) {
 return Object.assign({}, obj, {[prop]: obj[prop] - value})
 }
 
 ngOnInit() {
 const leftArrow$ = Observable.fromEvent(document, 'keydown')
 .filter(event => event.key === 'ArrowLeft')
 .mapTo(position => this.decrement(position, 'x', 10));
 
 const rightArrow$ = Observable.fromEvent(document, 'keydown')
 .filter(event => event.key === 'ArrowRight')
 .mapTo(position => this.increment(position, 'x', 10));
 
 Observable.merge(leftArrow$, rightArrow$)
 .startWith({x: 100, y: 100})
 .scan((acc, curr) => curr(acc))
 .subscribe(result => this.position = result);
 }
  • 45. How can we sequence a stream?
  • 46. @ViewChild('ball') ball;
 position: any;
 
 ngOnInit() {
 const OFFSET = 50;
 const move$ = Observable.fromEvent(document, 'mousemove')
 .map(event => {
 return {x: event.pageX - OFFSET, y: event.pageY - OFFSET};
 });
 
 const down$ = Observable.fromEvent(this.ball.nativeElement, 'mousedown');
 
 down$
 .switchMap(event => move$)
 .startWith({ x: 100, y: 100})
 .subscribe(result => this.position = result);
 }
  • 47. @ViewChild('ball') ball;
 position: any;
 
 ngOnInit() {
 const OFFSET = 50;
 const move$ = Observable.fromEvent(document, 'mousemove')
 .map(event => {
 return {x: event.pageX - OFFSET, y: event.pageY - OFFSET};
 });
 
 const down$ = Observable.fromEvent(this.ball.nativeElement, 'mousedown');
 
 down$
 .switchMap(event => move$)
 .startWith({ x: 100, y: 100})
 .subscribe(result => this.position = result);
 }
  • 48. @ViewChild('ball') ball;
 position: any;
 
 ngOnInit() {
 const OFFSET = 50;
 const move$ = Observable.fromEvent(document, 'mousemove')
 .map(event => {
 return {x: event.pageX - OFFSET, y: event.pageY - OFFSET};
 });
 
 const down$ = Observable.fromEvent(this.ball.nativeElement, 'mousedown');
 
 down$
 .switchMap(event => move$) 
 .startWith({ x: 100, y: 100}) .subscribe(result => this.position = result);
 }
  • 49. @ViewChild('ball') ball;
 position: any;
 
 ngOnInit() {
 const OFFSET = 50;
 const move$ = Observable.fromEvent(document, 'mousemove')
 .map(event => {
 return {x: event.pageX - OFFSET, y: event.pageY - OFFSET};
 });
 
 const down$ = Observable.fromEvent(this.ball.nativeElement, 'mousedown');
 
 down$
 .switchMap(event => move$) 
 .startWith({ x: 100, y: 100}) .subscribe(result => this.position = result);
 }
  • 50. @ViewChild('ball') ball;
 position: any;
 
 ngOnInit() {
 const OFFSET = 50;
 const move$ = Observable.fromEvent(document, 'mousemove')
 .map(event => {
 return {x: event.pageX - OFFSET, y: event.pageY - OFFSET};
 });
 
 const down$ = Observable.fromEvent(this.ball.nativeElement, 'mousedown');
 const up$ = Observable.fromEvent(document, 'mouseup');
 
 down$
 .switchMap(event => move$.takeUntil(up$))
 .startWith({ x: 100, y: 100})
 .subscribe(result => this.position = result);
 }
  • 52. What effect does the origin of the stream have on the output?
  • 53. <div class="container">
 <app-line
 *ngFor="let line of lines" [line]="line">
 </app-line>
 </div>
  • 54. <svg>
 <line [attr.x1]="line.x1" [attr.y1]="line.y1"
 [attr.x2]="line.x2" [attr.y2]="line.y2"
 style="stroke:rgb(255,0,0);stroke-width:2"/>
 </svg>
  • 55. lines: any[] = [];
 ngOnInit() {
 Observable.fromEvent(document, 'click')
 .map(event => {
 return {x: event.pageX, y: event.pageY};
 })
 .pairwise(2)
 .map(positions => {
 const p1 = positions[0];
 const p2 = positions[1];
 return { x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y };
 })
 .subscribe(line => this.lines = [...this.lines, line]);
 }
  • 57. lines: any[] = [];
 ngOnInit() {
 Observable.fromEvent(document, 'mousemove')
 .map(event => {
 return {x: event.pageX, y: event.pageY};
 })
 .pairwise(2)
 .map(position => {
 const p1 = positions[0];
 const p2 = positions[1];
 return { x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y };
 })
 .subscribe(line => this.lines = [...this.lines, line]);
 }
  • 59. What are some fun things we can do with a stream?
  • 60. @ViewChild('ball') ball;
 ngOnInit() {
 const OFFSET = 50;
 
 Observable.fromEvent(document, 'click')
 .map(event => {
 return {x: event.clientX - OFFSET, y: event.clientY - OFFSET}
 })
 .subscribe(props => TweenMax.to(this.ball.nativeElement, 1, props))
 }
  • 62. What are some MOAR fun things we can do with a stream?
  • 63. circles: any[] = [];
 ngOnInit() {
 const OFFSET = 25; 
 Observable.fromEvent(document, 'mousemove')
 .map(event => {
 return { x: event.clientX - OFFSET, y: event.clientY - OFFSET}
 })
 .subscribe(circle => this.circles = [ ...this.circles, circle])
 }
  • 64. <div class="container">
 <app-circle
 *ngFor="let circle of circles"
 [style.left]="circle.x + 'px'"
 [style.top]="circle.y + 'px'">
 </app-circle>
 </div>
  • 65. export class CircleComponent implements OnInit {
 @ViewChild('circle') circle;
 
 ngOnInit() {
 TweenMax.to(this.circle.nativeElement, 2, 
 {alpha: 0, width: 0, height: 0});
 }
 }
  • 70. import { AngularFireModule } from 'angularfire2'; export const firebaseConfig = {
 apiKey: 'PETERBACONDARWINISABEASTINSHEEPSCLOTHING',
 authDomain: 'rxjsbeastmode.firebaseapp.com',
 databaseURL: 'https://rxjsbeastmode.firebaseio.com',
 storageBucket: ''
 };
 @NgModule({
 declarations: [AppComponent],
 imports: [
 BrowserModule,
 AngularFireModule.initializeApp(firebaseConfig),
 ],
 bootstrap: [AppComponent]
 })
 export class AppModule {}
  • 71. import { AngularFireModule } from 'angularfire2'; export const firebaseConfig = {
 apiKey: 'PETERBACONDARWINISABEASTINSHEEPSCLOTHING',
 authDomain: 'rxjsbeastmode.firebaseapp.com',
 databaseURL: 'https://rxjsbeastmode.firebaseio.com',
 storageBucket: ''
 };
 @NgModule({
 declarations: [AppComponent],
 imports: [
 BrowserModule,
 AngularFireModule.initializeApp(firebaseConfig),
 ],
 bootstrap: [AppComponent]
 })
 export class AppModule {}
  • 73. const remote$ = this.af.database.object('clicker/');
 
 remote$
 .subscribe(result => this.count = result.ticker);
  • 75. const remote$ = this.af.database.object('clicker/');
 
 Observable.fromEvent(this.getNativeElement(this.btn), 'click')
 .startWith({ticker: 0})
 .scan((acc, curr) => { return { ticker: acc.ticker + 1 }; })
 .subscribe(event => remote$.update(event));
  • 76. const remote$ = this.af.database.object('clicker/');
 // Outgoing
 Observable.fromEvent(this.getNativeElement(this.btn), 'click')
 .startWith({ticker: 0})
 .scan((acc, curr) => { return { ticker: acc.ticker + 1 }; })
 .subscribe(event => remote$.update(event));
 // Incoming
 remote$
 .subscribe(result => this.message = result.message);
  • 77. const remote$ = this.af.database.object('clicker/');
 // Outgoing ——>
 Observable.fromEvent(this.getNativeElement(this.btn), 'click')
 .startWith({ticker: 0})
 .scan((acc, curr) => { return { ticker: acc.ticker + 1 }; })
 .subscribe(event => remote$.update(event));
 // <—— Incoming
 remote$
 .subscribe(result => this.message = result.message);
  • 92.