SlideShare une entreprise Scribd logo
1  sur  136
Télécharger pour lire hors ligne
Georgios Kaleadis
· @deluxee (Twitter)
· @georgiee (Github)
· Workshop Repository
· Working for Satellytes, Munich
What's in the box?
· Dec 05 - Dec 07 2018
· Level: Intermediate/Advanced
· Angular 7
· 1st & 2nd day: Workshop
· 3th day: Hackathon (tensorflow, remote
games)
Everything is here:
github.com/georgiee/angular-workshop-
skipbo
6 Chapters
THEORY
CHALLENGE
RESULT
END RESULT
Skip-Bo Core
& Oscar
SCHEDULE
Day 2
· Chapter 04 — RxJS
· Chapter 05 — Testing
· Chapter 06 — Animation
Day 1
· Chapter 01 — Modules
· Chapter 02 — Components
· Chapter 03 — Routing
DAY 1
Chapter I
MODULES
"What would you have
ripped out of Angular if
you had one breaking
change for free ?"
NgModules
— Igor Minar, AngularConnect 2018
THEORY
· Providers
· Declarations
· Imports/Exports
· EntryComponents
· Bootstrap
· Schema
Providers
· provider array
· { provide: Token, useClass: Value }
· InjectionToken
· providedIn 'root' or OtherModule
· (Greeting Example)
Declarations
· components, pipes and directives
· tell Angular about their existence — once!
· SharedModules, FeatureModule, per
Element Module
Imports/Exports
· Export: What to use outside
· Import: What to use inside
· (ButtonModule Example)
EntryComponents
· For dynamic components
· Routers do this this automatically for you
· (Dynamic Example)
Bootstrap
· Define your app root component
· There can be multiple app roots
· (Example)
Schemas
· CUSTOM_ELEMENTS_SCHEMA
· <my-component my-prop="lorem">
· NO_ERRORS_SCHEMA: anything
· (Example)
CHALLENGE
Your tasks
· Create our GameService
· Provide expected interface (TDD)
· Inject the GameService
· Break the Injection and fix it
· Answer a quick question
RESULT
Chapter II
COMPONENTS
THEORY
· Introduction
· preserveWhitespaces
· Selectors on existing elements
· View Encapsulation
· Smart & Dumb Components
· OnPush
· Template References
Introduction
A component controls a patch of screen
called a view.
· Meta, Component Class, Template
· Directive vs. Components
preserveWhitespaces
<button>1</button>
<button>2</button>
<button>3</button>
vs
<button>1</button><button>2</button><button>3</button>
Selectors
<my-custom-component></my-custom-component>
<some-component myDirective></some-component>
What about Components on existing
Elements?
View Encapsulation
· BEM anyone?
· Scoped Styles in ShadowDOM standard
!
· Angular Native & Emulated
· Native 0, ShadowDom 1
· (Example)
Smart & Dumb
· presentational not dumb!
· presentational: rely on inputs only, no
huge logic inside
· smart: state, sometimes business logic,
fetch data
· (Example)
OnPush
· Important Concept but CD makes it
difficult
· Rely only on inputs (presentational )
· Performance: Website Example
· Still updating: UI events, Async Pipes
· Live Example
Template References
· exportAs
· #myComponent1='myAppOne'
· Live Example
CHALLENGE
Your tasks
· Create Components
· Use Gameplay Component
· Use CardPile Component
· Fix Bug in the CardPile
· Inject parent component
RESULT
Chapter III
ROUTING
THEORY
· Router Outlet
· Lazy Load
· Manual Loading a Module
· Guards
· Resolver
Router Outlet
· Anchor point for mounted components
· Exposes reference #myTemplateVar="outlet"
Lazy Load
So easy to do.
loadChildren: './lazy-load/lazy-load.module#LazyLoadModule'
· Works by convention
· Usually you use a empty route inside.
· (Example)
Manual Loading a Module
· lazyModules key in angular.json
· creates a chunk
· load by convention url
· Use it with NgModuleFactoryLoader
· (Example)
Guards
· Protect your pages
· Interfaces: CanActivate, CanDeactivate, ..
· ng g guard my-protector
· (Example)
Resolver
· Ensure a component gets its data
· Access via route.snapshot.data
· Example
CHALLENGE
Your tasks
· Route to the new pages
· Make GameModule lazy load
· Routing Guards: CanActivate
· Routing Guards: CanDeactivate with
prompt
RESULT
END 1
· @deluxee (Twitter)
· @georgiee (Github)
· Workshop Repository
· Workshop Project
RECAP
Day 1
· Chapter I — Modules
· Chapter II — Components
· Chapter III — Routing
DAY 2
Schedule
· Chapter IV — RxJS
· Chapter V — Testing
· Chapter VI — Animation
Chapter IV
RXJS
THEORY
· Introduction
· Debugging
· About Dollar Signs
· Cold vs Hot Observables
· Make Cold Observables Hot
· RxJS in the wild
· Testing
Introduction
· Extended Observer Pattern (Gang of Four)
· Subject and Observers
· Event System is an Observer Pattern
Chapter 04 — RxJS: Introduction
of(1, 2, 3, 4, 5, 6)
.pipe(
take(3),
filter(value => value%2 === 0),
).subscribe()
);
Chapter 04 — RxJS: Introduction
Debugging
Tap
fromEvent(window, 'keydown')
.pipe(
tap(event => console.log('key pressed'))
).subscribe();
Chapter 04 — RxJS: Debugging
RxJS Spy (Tool)
import { tag } from 'rxjs-spy/operators/tag';
fromEvent(window, 'keydown')
.pipe(
tag('
!
Key'),
).subscribe();
Chapter 04 — RxJS: Debugging
Tag =
!
Key; notification = subscribe<br>
Tag =
!
Key; notification = next; value = {key: "a"…}
Tag =
!
Key; notification = next; value = {key: "b"…}
!
Key notification = unsubscribe<br>
Chapter 04 — RxJS: Debugging
Dollar Sign
const click$ = Observable.fromEvent(button, 'click');
· pluralization, called Finnish notation
· peopl€, mic€, oxe₦
Cold vs Hot Observables
A cold observable creates its producer on
each subscription, a hot observables closes
over an already existing instance.
— Ben Lesh
Chapter 04 — RxJS: Cold vs Hot
// COLD (unicast)
var cold = new Observable((observer) => {
var producer = new Producer();
producer.listen(() => {
observer.next()
});
});
// HOT (multicast)
var producer = new Producer();
var hot = new Observable((observer) => {
producer.listen(() => {
observer.next()
});
});
Chapter 04 — RxJS: Cold vs Hot
Make Cold Observable Hot
· Cold: Create a producer (like a
websocket) for each subscriber
· Make Hot: Create only one producer,
then send same data to all susbcribers
Chapter 04 — RxJS: Make Cold Observable Hot
const myInterval = interval(500).pipe(
tap(value => console.log('interval produced a value'))
);
myInterval.subscribe(value => {
console.log('received a value', value)
});
myInterval.subscribe(value => {
console.log('received a value', value)
});
/**
interval produced a value
received a value 0
interval produced a value
received a value 0
*/
Chapter 04 — RxJS: Make Cold Observable Hot
const myInterval = interval(500).pipe(
tap(value => console.log('interval produced a value'))
);
const subject = new Subject();
// 1. let this subject subscribe to the cold observable
myInterval.subscribe(subject);
// 2. now let future observables subscribe to the subject instead of the interval
subject.subscribe(value => console.log('received a value', value));
subject.subscribe(value => console.log('received a value', value));
subject.subscribe(value => console.log('received a value', value));
/**
interval produced a value
received a value 0
received a value 0
received a value 0
*/
Chapter 04 — RxJS: Make Cold Observable Hot
RxJS in the wild
· asObservable vs. Subject
· BehaviourSubject
· destroy & takeUntil
· toArray
private _changed: Subject<any> = new Subject();
get changed(): Observable<any> {
return this._changed.asObservable();
}
· A subject is both an observer and
observable
· Prevent the observer part (next)
· changed.next('new value')
Chapter 04 — RxJS: RxJS in the wild
· Hot Observables can produce values
without someone listening.
· Page mounted vs Data already
delivered
!
· BehaviorSubject is the solution
Chapter 04 — RxJS: RxJS in the wild
const subjectA = new Subject();
const subjectB = new BehaviorSubject(null);
subjectA.next('your loaded data');
subjectB.next('your loaded data');
subjectA.subscribe(value => console.log('value from subjectA:', value));
subjectB.subscribe(value => console.log('value from subjectB:', value));
// value from subjectB: your loaded data
Chapter 04 — RxJS: RxJS in the wild
· addEvenListener -> removeEventListener
· subscribe -> unsubscribe
· This is bad
class YourComponent {
initService() {
this.yourService.subscribe(data => {
// do something nice
})
}
}
Chapter 04 — RxJS: RxJS in the wild
private _subscription: Subscription = Subscription.EMPTY;
initService() {
this._subscription = this.yourService.subscribe();
}
ngOnDestroy() {
this._subscription.unsubscribe();
}
Chapter 04 — RxJS: RxJS in the wild
private _destroyed: Subject<any> = new Subject();
initService() {
this.yourService
.pipe(
takeUntil(this._destroyed)
).subscribe(data => {
// do something nice
})
}
ngOnDestroy() {
this._destroyed.next();
}
Chapter 04 — RxJS: RxJS in the wild
RxJS Testing
· RxJS is basically synchronous
· Test for effects, don't test the stream
itself.
· Forward time with tick & fakeAsync
· Never use Marble Testing to test streams
· (Example rxjs/testing)
CHALLENGE
Your tasks
· Redirect to the Gameover Page
· AI
!
Autoplay V1
· AI
!
Autoplay V2
· AI
!
Autoplay V3
· Stop the AI after game is over
RESULT
Chapter V
TESTING
THEORY
· Setup
· Component Testing
· Micro & Macro Tasks (Theory)
· Testing Async Code
· Change Detection
· Testing Routing
Setup
· Different Reporter (mocha
vs progress (default))
· Headless (no browser
window)
· Firefox als works Headless
!
· No, not IE.
Component Testing
· Angular CLI default is not good
beforeEach(() => {
fixture = TestBed.createComponent(SomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
TestBed.configureTestingModule({
declarations: [ FooComponent, TestSomeComponent ]
})
it('should create v2', () => {
const myFixture=TestBed.createComponent(TestSomeComponent);
myFixture.componentInstance.helperVariable = 345;
fixture.detectChanges();
expect(myFixture.componentInstance.myComponent).toBeTruthy();
});
@Component({ template: `<app-some [myInput]="helperVariable"></app-some>` })
class TestSomeComponent {
public helperVariable = 123;
@ViewChild(SomeComponent) myComponent: SomeComponent;
}
Chapter 04 — RxJS: Component Testing
Micro & Macro Tasks
What's the output ?
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
console.log('script end');
Chapter 05 — Testing: Micro & Macro Tasks
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
console.log('script end');
/*
script start
script end
promise1
promise2
setTimeout
*/
Chapter 05 — Testing: Micro & Macro Tasks
What are Macro Tasks?
Queued up but allow the browser engine
to render between each task.
· scripts
· setTimeout / setInterval
· event listener callbacks
document.appendChild(el);
el.style.display = 'none';
Chapter 05 — Testing: Micro & Macro Tasks
What are Microtasks?
They are queued up and executed at the
end of a task. No browser action in
between.
· MutationObserver callback (DOM
changes)
· Promises (even settled ones)
Chapter 05 — Testing: Micro & Macro Tasks
// endless (macro) tasks queue - is useless but okay
function cb() {
console.log('cb');
setTimeout(cb, 0)
}
cb();
//
⚠ ⚠ ⚠
This will hang your browser
// — save everything then try
"
function cb() {
console.log('cb');
Promise.resolve().then(cb);
}
cb();
Chapter 05 — Testing: Micro & Macro Tasks
Testing Async Code
· What is async ?
· ngZone Primer
· fakeAsync & tick + flush
· async & fixture.whenStable
· done (jasmine)
Chapter 05 — Testing: Testing Async Code
What is async?
· User does something
· Time passes
· Nothing else can change your application
Ever wondered what ngZone is ? Here a
ngZone Primer
· Zone.setInterval()
· Zone.alert()
· Zone.prompt()
· Zone.requestAnimationFrame()
· Zone.addEventListener()
Chapter 05 — Testing: Testing Async Code
it('setTimeout & tick & flushMicrotasks ', fakeAsync(() => {
let state = [];
Promise.resolve().then(function() {
state.push('promise result');
});
setTimeout(() => { state.push('timeout called'); });
setTimeout(() => { state.push('timeout called after 2s'); }, 2000);
expect(state).toEqual([]);
flushMicrotasks();
expect(state).toEqual(['promise result']);
tick();
expect(state).toEqual(['promise result', 'timeout called']);
tick(2000);
expect(state).toEqual(['promise result', 'timeout called', 'timeout called after 2s']);
}));
Chapter 05 — Testing: Testing Async Code
it('setTimeout(0) & tick ', fakeAsync(() => {
let state = [];
setTimeout(() => { state.push('timeout called'); });
setTimeout(() => { state.push('timeout called after 2s'); }, 2000);
expect(state).toEqual([]);
// tick wont' work -> Error: 1 timer(s) still in the queue.
// tick();
flush();
expect(state).toEqual(['timeout called', 'timeout called after 2s']);
}));
Chapter 05 — Testing: Testing Async Code
· async & fixture.whenStable
· done
it('manually finish your spec', (done) => {
console.log('run');
expect(true).toBe(true);
done();
});
Chapter 05 — Testing: Testing Async Code
If you expect changes in
your template call
!
fixture.detectChanges()
Chapter 05 — Testing: Testing Async Code
Testing Routing
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes(routes),/*...*/
],
declarations: [/*...*/],
}).compileComponents();
router = TestBed.get(Router);
location = TestBed.get(Location);
fixture = TestBed.createComponent(AppComponent);
}));
describe('application routing', () => {
it('navigate to "" redirects you to /welcome', fakeAsync(() => {
fixture.ngZone.run(() => router.navigate(['']));
tick();
expect(location.path()).toBe('/welcome');
}));
});
CHALLENGE
Your tasks
· Stock Bug (Investigate)
· Stock Bug — Part 1, 2, 3
· Test RxJS w/ Oscar
"
— CPUs
· Test RxJS w/ Oscar
"
— Humans
· Can Oscar play multiple cards ?
RESULT
Chapter VI
ANIMATION
THEORY
· Animation Basics
· Appear & Disappear
· Numeric Triggers
· Disable
· Router Animations
· Animate Children
@Component({
selector: 'app-my',
template: 'hello animations',
animations: [
trigger('stateAnimation', [
state('on', style({
backgroundColor: 'red'
})),
state('off', style({
backgroundColor: 'green'
})),
])
]
})
export class MyComponent {
@HostBinding('@stateAnimation')
public state = 'on';
@HostListener('click')
toggleState() {
this.state = this.state === 'on' ? 'off' : 'on';
}
}
Chapter 06 — Animation: Basics
animations: [
trigger('stateAnimation', [
...
]),
transition('on => off', [
animate('1s')
]),
transition('off => on', [
animate('1s')
])
]
Chapter 06 — Animation: Basics
animations: [
trigger('stateAnimation', [
...
]),
// Variant A
transition('off => on, off => on', [
animate('1s')
])
// Variant B
transition('* => *', [
animate('1s')
])
]
Chapter 06 — Animation: Basics
animate(1000);
animate('1s');
animate('5s 250ms');
animate('5s 10ms cubic-bezier(.17,.67,.88,.1)');
animate(500, style({ background: "blue" })));
// ...
!
:host {
transition: background-color 1s;
}
Chapter 06 — Animation: Basics
<div [@stateAnimation]='valueOrState'></div>
@Component({...})
class MyComponent {
@HostBinding('@stateAnimation')
public valueOrState: 'on'|'off' = 'on'
}
Chapter 06 — Animation: Basics (Target)
Appear & Disappear
transition('void => *' ,...)
transition(':enter' ,...)
transition('* => void' ,...)
transition(':leavce' ,...)
animations: [
trigger('stateAnimation', [
state('on', style({
backgroundColor: 'yellow'
})),
state('off', style({
backgroundColor: 'green'
})),
transition('on => off, off => on', [
animate('0.5s')
]),
transition(':enter', [
style({
height: 0,
backgroundColor: 'green',
overflow: 'hidden'
}),
animate('0.5s',
style({
height: '*',
overflow: 'auto'
})
)
])
])
]
Chapter 06 — Animation: Appear & Disappear
Disable
<div [@boxCounter]="boxCounter" [@.disabled]="true">
<div *ngFor="let items of boxes" class="box"></div>
</div>
<!-- won't disable, parent is the master -->
<div [@boxCounter]="boxCounter">
<div *ngFor="let items of boxes" class="box" [@.disabled]="true"></div>
</div>
Events
<div
[@animateAnyChange]="counter"
(@animateAnyChange.start)="start($event)"
(@animateAnyChange.done)="end($event)">
</div>
<!--
{element: ..., triggerName: "animateAnyChange", fromState: 0, toState: 1, phaseName: "start", …}
{element: ..., triggerName: "animateAnyChange", fromState: 0, toState: 1, phaseName: "done", …}
{element: ..., triggerName: "animateAnyChange", fromState: 1, toState: 2, phaseName: "start", …}
-->
More in the box:
· Query to target children elements
· Group vs. Sequence
· Stagger to insert small delays between
elements
animations: [
trigger('animateAnyChange', [
transition('* => *', [
group([
query('h1', [
style({ backgroundColor: 'red'}),
animate('1s')
]),
query('p', [
style({ backgroundColor: 'red'}),
animate('0.25s')
]),
query('button', [
style({ backgroundColor: 'yellow'}),
animate('0.5s')
]),
]),
])
])
]
animations: [
trigger('animateAnyChange', [
transition('* => *', [
sequence([
query('h1', [
style({ backgroundColor: 'red'}),
animate('1s')
]),
query('p', [
style({ backgroundColor: 'red'}),
animate('0.25s')
]),
query('button', [
style({ backgroundColor: 'yellow'}),
animate('0.5s')
]),
]),
])
])
]
animations: [
trigger('animateAnyChange', [
transition('* => *', [
query('h1, p', [
style({ opacity: 0, transform: 'translateY(-100px)'}),
stagger(-250, [
animate('500ms cubic-bezier(0.35, 0, 0.25, 1)',
style({ opacity: 1, transform: 'none' })
)
])
])
])
])
]
Router
Animations
animations: [
trigger('routeAnimation', [
transition('* => *', [
group([
query(':enter', [
style({ transform: 'translateX(100%)' }),
animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))
], { optional: true }),
query(':leave', [
animate('0.5s ease-in-out', style({
transform: 'translateY(100%)',
opacity: 0
}))
], { optional: true })
])
])
])
]
<a routerLink='a'>go to a</a><br>
<a routerLink='b'>go to b</a>
<div
[@routeAnimation]="yourOutlet.isActivated && yourOutlet.activatedRoute.routeConfig.path"
(@routeAnimation.start)="start($event)"
(@routeAnimation.done)="end($event)">
<router-outlet #yourOutlet="outlet"></router-outlet>
</div>
animateChild
query('@yourNestedTrigger', [
animateChild()
], { optional: true })
CHALLENGE
Your tasks
· First Flip - Part 1 & 2
· Flip Party
· Flip with Style
· Make the Hand Cards flip
· Animate Stock Flip
RESULT
END 2
THANKS· @deluxee (Twitter)
· @georgiee (Github)
· Workshop Repository
· Workshop Project

Contenu connexe

Tendances

Callbacks and control flow in Node js
Callbacks and control flow in Node jsCallbacks and control flow in Node js
Callbacks and control flow in Node jsThomas Roch
 
Building Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJavaBuilding Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJavaRick Warren
 
Gerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRxGerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRxLoiane Groner
 
Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018Loiane Groner
 
Apache Sling - Distributed Eventing, Discovery, and Jobs (adaptTo 2013)
Apache Sling - Distributed Eventing, Discovery, and Jobs (adaptTo 2013)Apache Sling - Distributed Eventing, Discovery, and Jobs (adaptTo 2013)
Apache Sling - Distributed Eventing, Discovery, and Jobs (adaptTo 2013)Carsten Ziegeler
 
Angular Optimization Web Performance Meetup
Angular Optimization Web Performance MeetupAngular Optimization Web Performance Meetup
Angular Optimization Web Performance MeetupDavid Barreto
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaFrank Lyaruu
 
Practical RxJava for Android
Practical RxJava for AndroidPractical RxJava for Android
Practical RxJava for AndroidTomáš Kypta
 
Testing React hooks with the new act function
Testing React hooks with the new act functionTesting React hooks with the new act function
Testing React hooks with the new act functionDaniel Irvine
 
RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015Constantine Mars
 
The Road To Reactive with RxJava JEEConf 2016
The Road To Reactive with RxJava JEEConf 2016The Road To Reactive with RxJava JEEConf 2016
The Road To Reactive with RxJava JEEConf 2016Frank Lyaruu
 
Reactive Thinking in Java
Reactive Thinking in JavaReactive Thinking in Java
Reactive Thinking in JavaYakov Fain
 
An Introduction to RxJava
An Introduction to RxJavaAn Introduction to RxJava
An Introduction to RxJavaSanjay Acharya
 
Full-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConf
Full-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConfFull-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConf
Full-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConfLoiane Groner
 
Rxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJavaRxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJavaKros Huang
 
Real world functional reactive programming
Real world functional reactive programmingReal world functional reactive programming
Real world functional reactive programmingEric Polerecky
 

Tendances (20)

Reactive Java (33rd Degree)
Reactive Java (33rd Degree)Reactive Java (33rd Degree)
Reactive Java (33rd Degree)
 
Callbacks and control flow in Node js
Callbacks and control flow in Node jsCallbacks and control flow in Node js
Callbacks and control flow in Node js
 
Building Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJavaBuilding Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJava
 
OHHttpStubs
OHHttpStubsOHHttpStubs
OHHttpStubs
 
Gerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRxGerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRx
 
Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018
 
Apache Sling - Distributed Eventing, Discovery, and Jobs (adaptTo 2013)
Apache Sling - Distributed Eventing, Discovery, and Jobs (adaptTo 2013)Apache Sling - Distributed Eventing, Discovery, and Jobs (adaptTo 2013)
Apache Sling - Distributed Eventing, Discovery, and Jobs (adaptTo 2013)
 
Angular Optimization Web Performance Meetup
Angular Optimization Web Performance MeetupAngular Optimization Web Performance Meetup
Angular Optimization Web Performance Meetup
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJava
 
Practical RxJava for Android
Practical RxJava for AndroidPractical RxJava for Android
Practical RxJava for Android
 
Testing React hooks with the new act function
Testing React hooks with the new act functionTesting React hooks with the new act function
Testing React hooks with the new act function
 
RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015
 
The Road To Reactive with RxJava JEEConf 2016
The Road To Reactive with RxJava JEEConf 2016The Road To Reactive with RxJava JEEConf 2016
The Road To Reactive with RxJava JEEConf 2016
 
Reactive Thinking in Java
Reactive Thinking in JavaReactive Thinking in Java
Reactive Thinking in Java
 
RxJava on Android
RxJava on AndroidRxJava on Android
RxJava on Android
 
An Introduction to RxJava
An Introduction to RxJavaAn Introduction to RxJava
An Introduction to RxJava
 
Full-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConf
Full-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConfFull-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConf
Full-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConf
 
Rxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJavaRxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJava
 
Real world functional reactive programming
Real world functional reactive programmingReal world functional reactive programming
Real world functional reactive programming
 
rx-java-presentation
rx-java-presentationrx-java-presentation
rx-java-presentation
 

Similaire à Angular Advanced Workshop (+ Challenges)

Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsJeff Durta
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxbobmcwhirter
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript EverywherePascal Rettig
 
Zend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarZend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarYonni Mendes
 
What to expect from Java 9
What to expect from Java 9What to expect from Java 9
What to expect from Java 9Ivan Krylov
 
Create ReactJS Component & publish as npm package
Create ReactJS Component & publish as npm packageCreate ReactJS Component & publish as npm package
Create ReactJS Component & publish as npm packageAndrii Lundiak
 
Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!Sylvain Wallez
 
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...GITS Indonesia
 
Test Automation for NoSQL Databases
Test Automation for NoSQL DatabasesTest Automation for NoSQL Databases
Test Automation for NoSQL DatabasesTobias Trelle
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiRan Mizrahi
 
Node.js Patterns for Discerning Developers
Node.js Patterns for Discerning DevelopersNode.js Patterns for Discerning Developers
Node.js Patterns for Discerning Developerscacois
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsJeff Durta
 
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3Elixir Club
 
How to make a high-quality Node.js app, Nikita Galkin
How to make a high-quality Node.js app, Nikita GalkinHow to make a high-quality Node.js app, Nikita Galkin
How to make a high-quality Node.js app, Nikita GalkinSigma Software
 
Introduction to Node.js
Introduction to Node.jsIntroduction to Node.js
Introduction to Node.jsVikash Singh
 
Functional Programming with JavaScript
Functional Programming with JavaScriptFunctional Programming with JavaScript
Functional Programming with JavaScriptMark Shelton
 
Standardizing JavaScript Decorators in TC39 (Full Stack Fest 2019)
Standardizing JavaScript Decorators in TC39 (Full Stack Fest 2019)Standardizing JavaScript Decorators in TC39 (Full Stack Fest 2019)
Standardizing JavaScript Decorators in TC39 (Full Stack Fest 2019)Igalia
 

Similaire à Angular Advanced Workshop (+ Challenges) (20)

Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBox
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript Everywhere
 
Zend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarZend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinar
 
What to expect from Java 9
What to expect from Java 9What to expect from Java 9
What to expect from Java 9
 
Create ReactJS Component & publish as npm package
Create ReactJS Component & publish as npm packageCreate ReactJS Component & publish as npm package
Create ReactJS Component & publish as npm package
 
Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!
 
Sprint 17
Sprint 17Sprint 17
Sprint 17
 
Lambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter LawreyLambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter Lawrey
 
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
 
Test Automation for NoSQL Databases
Test Automation for NoSQL DatabasesTest Automation for NoSQL Databases
Test Automation for NoSQL Databases
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran Mizrahi
 
Node.js Patterns for Discerning Developers
Node.js Patterns for Discerning DevelopersNode.js Patterns for Discerning Developers
Node.js Patterns for Discerning Developers
 
Twins: OOP and FP
Twins: OOP and FPTwins: OOP and FP
Twins: OOP and FP
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
 
How to make a high-quality Node.js app, Nikita Galkin
How to make a high-quality Node.js app, Nikita GalkinHow to make a high-quality Node.js app, Nikita Galkin
How to make a high-quality Node.js app, Nikita Galkin
 
Introduction to Node.js
Introduction to Node.jsIntroduction to Node.js
Introduction to Node.js
 
Functional Programming with JavaScript
Functional Programming with JavaScriptFunctional Programming with JavaScript
Functional Programming with JavaScript
 
Standardizing JavaScript Decorators in TC39 (Full Stack Fest 2019)
Standardizing JavaScript Decorators in TC39 (Full Stack Fest 2019)Standardizing JavaScript Decorators in TC39 (Full Stack Fest 2019)
Standardizing JavaScript Decorators in TC39 (Full Stack Fest 2019)
 

Dernier

Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 

Dernier (20)

Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 

Angular Advanced Workshop (+ Challenges)

  • 1.
  • 2. Georgios Kaleadis · @deluxee (Twitter) · @georgiee (Github) · Workshop Repository · Working for Satellytes, Munich
  • 3. What's in the box? · Dec 05 - Dec 07 2018 · Level: Intermediate/Advanced · Angular 7 · 1st & 2nd day: Workshop · 3th day: Hackathon (tensorflow, remote games)
  • 8.
  • 11. Day 2 · Chapter 04 — RxJS · Chapter 05 — Testing · Chapter 06 — Animation
  • 12. Day 1 · Chapter 01 — Modules · Chapter 02 — Components · Chapter 03 — Routing
  • 13. DAY 1
  • 15. "What would you have ripped out of Angular if you had one breaking change for free ?"
  • 16. NgModules — Igor Minar, AngularConnect 2018
  • 18. · Providers · Declarations · Imports/Exports · EntryComponents · Bootstrap · Schema
  • 19. Providers · provider array · { provide: Token, useClass: Value } · InjectionToken · providedIn 'root' or OtherModule · (Greeting Example)
  • 20. Declarations · components, pipes and directives · tell Angular about their existence — once! · SharedModules, FeatureModule, per Element Module
  • 21. Imports/Exports · Export: What to use outside · Import: What to use inside · (ButtonModule Example)
  • 22. EntryComponents · For dynamic components · Routers do this this automatically for you · (Dynamic Example)
  • 23. Bootstrap · Define your app root component · There can be multiple app roots · (Example)
  • 24. Schemas · CUSTOM_ELEMENTS_SCHEMA · <my-component my-prop="lorem"> · NO_ERRORS_SCHEMA: anything · (Example)
  • 26. Your tasks · Create our GameService · Provide expected interface (TDD) · Inject the GameService · Break the Injection and fix it · Answer a quick question
  • 28.
  • 31. · Introduction · preserveWhitespaces · Selectors on existing elements · View Encapsulation · Smart & Dumb Components · OnPush · Template References
  • 32. Introduction A component controls a patch of screen called a view. · Meta, Component Class, Template · Directive vs. Components
  • 35. View Encapsulation · BEM anyone? · Scoped Styles in ShadowDOM standard ! · Angular Native & Emulated · Native 0, ShadowDom 1 · (Example)
  • 36. Smart & Dumb · presentational not dumb! · presentational: rely on inputs only, no huge logic inside · smart: state, sometimes business logic, fetch data · (Example)
  • 37. OnPush · Important Concept but CD makes it difficult · Rely only on inputs (presentational ) · Performance: Website Example · Still updating: UI events, Async Pipes · Live Example
  • 38. Template References · exportAs · #myComponent1='myAppOne' · Live Example
  • 40. Your tasks · Create Components · Use Gameplay Component · Use CardPile Component · Fix Bug in the CardPile · Inject parent component
  • 42.
  • 45. · Router Outlet · Lazy Load · Manual Loading a Module · Guards · Resolver
  • 46. Router Outlet · Anchor point for mounted components · Exposes reference #myTemplateVar="outlet"
  • 47. Lazy Load So easy to do. loadChildren: './lazy-load/lazy-load.module#LazyLoadModule' · Works by convention · Usually you use a empty route inside. · (Example)
  • 48. Manual Loading a Module · lazyModules key in angular.json · creates a chunk · load by convention url · Use it with NgModuleFactoryLoader · (Example)
  • 49. Guards · Protect your pages · Interfaces: CanActivate, CanDeactivate, .. · ng g guard my-protector · (Example)
  • 50. Resolver · Ensure a component gets its data · Access via route.snapshot.data · Example
  • 52. Your tasks · Route to the new pages · Make GameModule lazy load · Routing Guards: CanActivate · Routing Guards: CanDeactivate with prompt
  • 54.
  • 55. END 1
  • 56.
  • 57. · @deluxee (Twitter) · @georgiee (Github) · Workshop Repository · Workshop Project
  • 58. RECAP
  • 59. Day 1 · Chapter I — Modules · Chapter II — Components · Chapter III — Routing
  • 60. DAY 2
  • 61. Schedule · Chapter IV — RxJS · Chapter V — Testing · Chapter VI — Animation
  • 64. · Introduction · Debugging · About Dollar Signs · Cold vs Hot Observables · Make Cold Observables Hot · RxJS in the wild · Testing
  • 65. Introduction · Extended Observer Pattern (Gang of Four) · Subject and Observers · Event System is an Observer Pattern Chapter 04 — RxJS: Introduction
  • 66.
  • 67. of(1, 2, 3, 4, 5, 6) .pipe( take(3), filter(value => value%2 === 0), ).subscribe() ); Chapter 04 — RxJS: Introduction
  • 68. Debugging Tap fromEvent(window, 'keydown') .pipe( tap(event => console.log('key pressed')) ).subscribe(); Chapter 04 — RxJS: Debugging
  • 69. RxJS Spy (Tool) import { tag } from 'rxjs-spy/operators/tag'; fromEvent(window, 'keydown') .pipe( tag(' ! Key'), ).subscribe(); Chapter 04 — RxJS: Debugging
  • 70. Tag = ! Key; notification = subscribe<br> Tag = ! Key; notification = next; value = {key: "a"…} Tag = ! Key; notification = next; value = {key: "b"…} ! Key notification = unsubscribe<br> Chapter 04 — RxJS: Debugging
  • 71. Dollar Sign const click$ = Observable.fromEvent(button, 'click'); · pluralization, called Finnish notation · peopl€, mic€, oxe₦
  • 72. Cold vs Hot Observables A cold observable creates its producer on each subscription, a hot observables closes over an already existing instance. — Ben Lesh Chapter 04 — RxJS: Cold vs Hot
  • 73. // COLD (unicast) var cold = new Observable((observer) => { var producer = new Producer(); producer.listen(() => { observer.next() }); }); // HOT (multicast) var producer = new Producer(); var hot = new Observable((observer) => { producer.listen(() => { observer.next() }); }); Chapter 04 — RxJS: Cold vs Hot
  • 74. Make Cold Observable Hot · Cold: Create a producer (like a websocket) for each subscriber · Make Hot: Create only one producer, then send same data to all susbcribers Chapter 04 — RxJS: Make Cold Observable Hot
  • 75. const myInterval = interval(500).pipe( tap(value => console.log('interval produced a value')) ); myInterval.subscribe(value => { console.log('received a value', value) }); myInterval.subscribe(value => { console.log('received a value', value) }); /** interval produced a value received a value 0 interval produced a value received a value 0 */ Chapter 04 — RxJS: Make Cold Observable Hot
  • 76. const myInterval = interval(500).pipe( tap(value => console.log('interval produced a value')) ); const subject = new Subject(); // 1. let this subject subscribe to the cold observable myInterval.subscribe(subject); // 2. now let future observables subscribe to the subject instead of the interval subject.subscribe(value => console.log('received a value', value)); subject.subscribe(value => console.log('received a value', value)); subject.subscribe(value => console.log('received a value', value)); /** interval produced a value received a value 0 received a value 0 received a value 0 */ Chapter 04 — RxJS: Make Cold Observable Hot
  • 77. RxJS in the wild · asObservable vs. Subject · BehaviourSubject · destroy & takeUntil · toArray
  • 78. private _changed: Subject<any> = new Subject(); get changed(): Observable<any> { return this._changed.asObservable(); } · A subject is both an observer and observable · Prevent the observer part (next) · changed.next('new value') Chapter 04 — RxJS: RxJS in the wild
  • 79. · Hot Observables can produce values without someone listening. · Page mounted vs Data already delivered ! · BehaviorSubject is the solution Chapter 04 — RxJS: RxJS in the wild
  • 80. const subjectA = new Subject(); const subjectB = new BehaviorSubject(null); subjectA.next('your loaded data'); subjectB.next('your loaded data'); subjectA.subscribe(value => console.log('value from subjectA:', value)); subjectB.subscribe(value => console.log('value from subjectB:', value)); // value from subjectB: your loaded data Chapter 04 — RxJS: RxJS in the wild
  • 81. · addEvenListener -> removeEventListener · subscribe -> unsubscribe · This is bad class YourComponent { initService() { this.yourService.subscribe(data => { // do something nice }) } } Chapter 04 — RxJS: RxJS in the wild
  • 82. private _subscription: Subscription = Subscription.EMPTY; initService() { this._subscription = this.yourService.subscribe(); } ngOnDestroy() { this._subscription.unsubscribe(); } Chapter 04 — RxJS: RxJS in the wild
  • 83. private _destroyed: Subject<any> = new Subject(); initService() { this.yourService .pipe( takeUntil(this._destroyed) ).subscribe(data => { // do something nice }) } ngOnDestroy() { this._destroyed.next(); } Chapter 04 — RxJS: RxJS in the wild
  • 84. RxJS Testing · RxJS is basically synchronous · Test for effects, don't test the stream itself. · Forward time with tick & fakeAsync · Never use Marble Testing to test streams · (Example rxjs/testing)
  • 86. Your tasks · Redirect to the Gameover Page · AI ! Autoplay V1 · AI ! Autoplay V2 · AI ! Autoplay V3 · Stop the AI after game is over
  • 88.
  • 91. · Setup · Component Testing · Micro & Macro Tasks (Theory) · Testing Async Code · Change Detection · Testing Routing
  • 92. Setup · Different Reporter (mocha vs progress (default)) · Headless (no browser window) · Firefox als works Headless ! · No, not IE.
  • 93. Component Testing · Angular CLI default is not good beforeEach(() => { fixture = TestBed.createComponent(SomeComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); });
  • 94. TestBed.configureTestingModule({ declarations: [ FooComponent, TestSomeComponent ] }) it('should create v2', () => { const myFixture=TestBed.createComponent(TestSomeComponent); myFixture.componentInstance.helperVariable = 345; fixture.detectChanges(); expect(myFixture.componentInstance.myComponent).toBeTruthy(); }); @Component({ template: `<app-some [myInput]="helperVariable"></app-some>` }) class TestSomeComponent { public helperVariable = 123; @ViewChild(SomeComponent) myComponent: SomeComponent; } Chapter 04 — RxJS: Component Testing
  • 95. Micro & Macro Tasks What's the output ? console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); Promise.resolve().then(function() { console.log('promise1'); }).then(function() { console.log('promise2'); }); console.log('script end'); Chapter 05 — Testing: Micro & Macro Tasks
  • 96. console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); Promise.resolve().then(function() { console.log('promise1'); }).then(function() { console.log('promise2'); }); console.log('script end'); /* script start script end promise1 promise2 setTimeout */ Chapter 05 — Testing: Micro & Macro Tasks
  • 97. What are Macro Tasks? Queued up but allow the browser engine to render between each task. · scripts · setTimeout / setInterval · event listener callbacks document.appendChild(el); el.style.display = 'none'; Chapter 05 — Testing: Micro & Macro Tasks
  • 98. What are Microtasks? They are queued up and executed at the end of a task. No browser action in between. · MutationObserver callback (DOM changes) · Promises (even settled ones) Chapter 05 — Testing: Micro & Macro Tasks
  • 99. // endless (macro) tasks queue - is useless but okay function cb() { console.log('cb'); setTimeout(cb, 0) } cb(); // ⚠ ⚠ ⚠ This will hang your browser // — save everything then try " function cb() { console.log('cb'); Promise.resolve().then(cb); } cb(); Chapter 05 — Testing: Micro & Macro Tasks
  • 100. Testing Async Code · What is async ? · ngZone Primer · fakeAsync & tick + flush · async & fixture.whenStable · done (jasmine) Chapter 05 — Testing: Testing Async Code
  • 101. What is async? · User does something · Time passes · Nothing else can change your application
  • 102. Ever wondered what ngZone is ? Here a ngZone Primer · Zone.setInterval() · Zone.alert() · Zone.prompt() · Zone.requestAnimationFrame() · Zone.addEventListener() Chapter 05 — Testing: Testing Async Code
  • 103. it('setTimeout & tick & flushMicrotasks ', fakeAsync(() => { let state = []; Promise.resolve().then(function() { state.push('promise result'); }); setTimeout(() => { state.push('timeout called'); }); setTimeout(() => { state.push('timeout called after 2s'); }, 2000); expect(state).toEqual([]); flushMicrotasks(); expect(state).toEqual(['promise result']); tick(); expect(state).toEqual(['promise result', 'timeout called']); tick(2000); expect(state).toEqual(['promise result', 'timeout called', 'timeout called after 2s']); })); Chapter 05 — Testing: Testing Async Code
  • 104. it('setTimeout(0) & tick ', fakeAsync(() => { let state = []; setTimeout(() => { state.push('timeout called'); }); setTimeout(() => { state.push('timeout called after 2s'); }, 2000); expect(state).toEqual([]); // tick wont' work -> Error: 1 timer(s) still in the queue. // tick(); flush(); expect(state).toEqual(['timeout called', 'timeout called after 2s']); })); Chapter 05 — Testing: Testing Async Code
  • 105. · async & fixture.whenStable · done it('manually finish your spec', (done) => { console.log('run'); expect(true).toBe(true); done(); }); Chapter 05 — Testing: Testing Async Code
  • 106. If you expect changes in your template call ! fixture.detectChanges() Chapter 05 — Testing: Testing Async Code
  • 107. Testing Routing beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ RouterTestingModule.withRoutes(routes),/*...*/ ], declarations: [/*...*/], }).compileComponents(); router = TestBed.get(Router); location = TestBed.get(Location); fixture = TestBed.createComponent(AppComponent); })); describe('application routing', () => { it('navigate to "" redirects you to /welcome', fakeAsync(() => { fixture.ngZone.run(() => router.navigate([''])); tick(); expect(location.path()).toBe('/welcome'); })); });
  • 109. Your tasks · Stock Bug (Investigate) · Stock Bug — Part 1, 2, 3 · Test RxJS w/ Oscar " — CPUs · Test RxJS w/ Oscar " — Humans · Can Oscar play multiple cards ?
  • 110. RESULT
  • 111.
  • 113. THEORY
  • 114. · Animation Basics · Appear & Disappear · Numeric Triggers · Disable · Router Animations · Animate Children
  • 115. @Component({ selector: 'app-my', template: 'hello animations', animations: [ trigger('stateAnimation', [ state('on', style({ backgroundColor: 'red' })), state('off', style({ backgroundColor: 'green' })), ]) ] }) export class MyComponent { @HostBinding('@stateAnimation') public state = 'on'; @HostListener('click') toggleState() { this.state = this.state === 'on' ? 'off' : 'on'; } } Chapter 06 — Animation: Basics
  • 116. animations: [ trigger('stateAnimation', [ ... ]), transition('on => off', [ animate('1s') ]), transition('off => on', [ animate('1s') ]) ] Chapter 06 — Animation: Basics
  • 117. animations: [ trigger('stateAnimation', [ ... ]), // Variant A transition('off => on, off => on', [ animate('1s') ]) // Variant B transition('* => *', [ animate('1s') ]) ] Chapter 06 — Animation: Basics
  • 118. animate(1000); animate('1s'); animate('5s 250ms'); animate('5s 10ms cubic-bezier(.17,.67,.88,.1)'); animate(500, style({ background: "blue" }))); // ...
  • 119. ! :host { transition: background-color 1s; } Chapter 06 — Animation: Basics
  • 120. <div [@stateAnimation]='valueOrState'></div> @Component({...}) class MyComponent { @HostBinding('@stateAnimation') public valueOrState: 'on'|'off' = 'on' } Chapter 06 — Animation: Basics (Target)
  • 121. Appear & Disappear transition('void => *' ,...) transition(':enter' ,...) transition('* => void' ,...) transition(':leavce' ,...)
  • 122. animations: [ trigger('stateAnimation', [ state('on', style({ backgroundColor: 'yellow' })), state('off', style({ backgroundColor: 'green' })), transition('on => off, off => on', [ animate('0.5s') ]), transition(':enter', [ style({ height: 0, backgroundColor: 'green', overflow: 'hidden' }), animate('0.5s', style({ height: '*', overflow: 'auto' }) ) ]) ]) ] Chapter 06 — Animation: Appear & Disappear
  • 123. Disable <div [@boxCounter]="boxCounter" [@.disabled]="true"> <div *ngFor="let items of boxes" class="box"></div> </div> <!-- won't disable, parent is the master --> <div [@boxCounter]="boxCounter"> <div *ngFor="let items of boxes" class="box" [@.disabled]="true"></div> </div>
  • 124. Events <div [@animateAnyChange]="counter" (@animateAnyChange.start)="start($event)" (@animateAnyChange.done)="end($event)"> </div> <!-- {element: ..., triggerName: "animateAnyChange", fromState: 0, toState: 1, phaseName: "start", …} {element: ..., triggerName: "animateAnyChange", fromState: 0, toState: 1, phaseName: "done", …} {element: ..., triggerName: "animateAnyChange", fromState: 1, toState: 2, phaseName: "start", …} -->
  • 125. More in the box: · Query to target children elements · Group vs. Sequence · Stagger to insert small delays between elements
  • 126. animations: [ trigger('animateAnyChange', [ transition('* => *', [ group([ query('h1', [ style({ backgroundColor: 'red'}), animate('1s') ]), query('p', [ style({ backgroundColor: 'red'}), animate('0.25s') ]), query('button', [ style({ backgroundColor: 'yellow'}), animate('0.5s') ]), ]), ]) ]) ]
  • 127. animations: [ trigger('animateAnyChange', [ transition('* => *', [ sequence([ query('h1', [ style({ backgroundColor: 'red'}), animate('1s') ]), query('p', [ style({ backgroundColor: 'red'}), animate('0.25s') ]), query('button', [ style({ backgroundColor: 'yellow'}), animate('0.5s') ]), ]), ]) ]) ]
  • 128. animations: [ trigger('animateAnyChange', [ transition('* => *', [ query('h1, p', [ style({ opacity: 0, transform: 'translateY(-100px)'}), stagger(-250, [ animate('500ms cubic-bezier(0.35, 0, 0.25, 1)', style({ opacity: 1, transform: 'none' }) ) ]) ]) ]) ]) ]
  • 129. Router Animations animations: [ trigger('routeAnimation', [ transition('* => *', [ group([ query(':enter', [ style({ transform: 'translateX(100%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' })) ], { optional: true }), query(':leave', [ animate('0.5s ease-in-out', style({ transform: 'translateY(100%)', opacity: 0 })) ], { optional: true }) ]) ]) ]) ] <a routerLink='a'>go to a</a><br> <a routerLink='b'>go to b</a> <div [@routeAnimation]="yourOutlet.isActivated && yourOutlet.activatedRoute.routeConfig.path" (@routeAnimation.start)="start($event)" (@routeAnimation.done)="end($event)"> <router-outlet #yourOutlet="outlet"></router-outlet> </div>
  • 132. Your tasks · First Flip - Part 1 & 2 · Flip Party · Flip with Style · Make the Hand Cards flip · Animate Stock Flip
  • 133. RESULT
  • 134.
  • 135. END 2
  • 136. THANKS· @deluxee (Twitter) · @georgiee (Github) · Workshop Repository · Workshop Project