1 of 105

Enterprise Software Development

2 of 105

Building Applications with Angular

By Matt Wicks, Luke Cook & Jean Thirion

3 of 105

Morning Tea

10:30am - 10:45am

Lunch

1pm - 2pm

Afternoon Tea

3:30pm - 3:45pm

Finish

5pm

4 of 105

House Keeping

  1. Facilities
  2. Break times
  3. Course Materials

5 of 105

We will share code on GitHub��https://github.com/SSWConsulting/ng-workshop-syd-oct-2024

6 of 105

Welcome !

  1. Navigate to courses.firebootcamp.com
  2. SSID: SSW-Guest�Imurderbug5

7 of 105

Agenda

Fundamentals & The Angular CLI

RxJS, Observables & Http

Components & Services

Component Communication & Routing

Reactive Forms

State Management

Modules & Code Splitting

Unit Testing

 

8 of 105

Who has used Angular?

Who has used React or Vue?

Who is using ngrx/ngxs?

Who has done unit testing?

9 of 105

Let’s get to know each other

Name?

Angular experience?

What you would like to get from the workshop?

10 of 105

11 of 105

  1. Navigate to courses.firebootcamp.com
  2. Install the Angular CLI
  3. Check the version of your Angular CLI is 18.x.
  4. Node.js version 20.x
  5. Order a good coffee ☕

12 of 105

13 of 105

@angular2

IT’S JUST “ANGULAR”

14 of 105

Speed & Performance

  • Optimised code generation
  • Ahead of time compilation (AoT)
  • Ivy rendering engine
  • Code Splitting
  • Server Side Rendering (Universal)
  • Bundles budgets

15 of 105

Productivity

  • Component Model
  • Template Syntax
  • TypeScript
  • Ng Schematics
  • Angular CLI ❤

16 of 105

Complete Framework

  • Routing
  • Testing
  • Internationalization
  • Animation
  • Accessibility
  • Production Build Tool

17 of 105

18 of 105

19 of 105

20 of 105

21 of 105

22 of 105

23 of 105

24 of 105

25 of 105

26 of 105

27 of 105

Component Tree

28 of 105

Component Tree

Todo

App

Component

Todo

Component

Todo List Component

Todo Edit

Component

29 of 105

NgModules

App Component

Todo

Component

Todo List Component

Todo Edit Component

Home Component

30 of 105

Angular itself is easy

... but it forces you to confront modern web development.

TypeScript

Module Loader

RxJS

JS

31 of 105

Superfast and cross platform

More productive

Complete framework

Opinionated - structured

Enterprise friendly

You can be more ambitious

Summary - What is Angular and Why Care ?

32 of 105

What’s new in Angular 16 (May 2023)

  • Angular Signals ! (Interoperable with RxJS 💫) - Watch

  • Angular Hydration

  • Ng new - - Standalone
  • [Re quired] @Input()
  • Improved tooling for standalone components, directives, and pipes
  • … and our usual dependency updates

https://blog.angular.io/angular-v16-is-here-4d7a28ec680d

33 of 105

What‘s new in Angular 17 (Nov 2023)

  • New Docs site - https://angular.dev
  • Stable Signals

  • Lazy Loading of Page Parts
  • Deferrable Views

  • Improved Server-side Rendering (SSR)
  • CLI/Build speed performance improvements

34 of 105

What‘s new in Angular 17

  • New Syntax for Control Flow

35 of 105

What‘s new in Angular 18 🔥🔥🔥 �(May 2024)

  • Experimental support for zoneless change detection
  • Material 3 stable
  • Deferrable views + control flow stable

SSR improvements:

  • i18n hydration support
  • Better debugging
  • Hydration support for Angular Material
  • Event replay powered by same library as Google Search

36 of 105

Let’s look at some code

👩‍💻

37 of 105

  1. npm install @angular/cli -g(should be 18.x)
  2. ng --version(should be 18.x)
  3. ng new firebootcamp-crm --prefix fbc --routing --style scss
  4. cd firebootcamp-crm
  5. ng serve -o

38 of 105

Lunch order

39 of 105

40 of 105

CRM - Module 8

RXJS AND OBSERVABLES

41 of 105

Modern web apps are composed of asynchronous events�

Async code seems hard to write, refactor and debug

42 of 105

RxJS

RxJS simplifies async code�

43 of 105

RxJS

An API for asynchronous programming

with observable streams

44 of 105

Observable�[]

Observer 1

[]

Observer 2

[]

45 of 105

Observable�[1]

Observer 1

[1]

Observer 2

[1]

46 of 105

Observable�[1, 4]

Observer 1

[1]

Observer 2

[1]

47 of 105

Observable�[1, 4]

Observer 1

[1, 4]

Observer 2

[1, 4]

48 of 105

Observable�[1, 4, 7]

Observer 1

[1, 4]

Observer 2

[1, 4]

49 of 105

Observable�[1, 4, 7]

Observer 1

[1, 4, 7]

Observer 2

[1, 4, 7]

50 of 105

.map(x => x + 1)

Observable�[1]

Observer 1

[2]

51 of 105

.map(x => x + 1)

Observable�[1,4]

Observer 1

[2]

52 of 105

.map(x => x + 1)

Observable�[1,4]

Observer 1

[2,5]

53 of 105

.map(x => x + 1)

Observable�[1,4,7]

Observer 1

[2,5]

54 of 105

.map(x => x + 1)

Observable�[1,4,7]

Observer 1

[2,5,8]

55 of 105

.map(x => x + 1)

.filter(x => x > 2)

Observable�[1,4,7]

Observer 1

[2,5,8]

Observer 2

[4,7]

56 of 105

.map(x => x + 1)

.filter(x => x > 2)

.reduce((x,y) => x + y)

Observable�[1,4,7]

Observer 1

[2,5,8]

Observer 2

[4,7]

57 of 105

.map(x => x + 1)

.filter(x => x > 2)

.reduce((x,y) => x + y)

Observable�[1,4,7]

Observer 1

[2,5,8]

Observer 2

[11]

58 of 105

Combination

combineAll

combineLatest

concat

concatAll

exhaust

forkJoin

merge

mergeAll

race

startWith

switch

withLatestFrom

zip

zipAll

Multicasting

cache

multicast

publish

publishBehavior

publishLast

publishReplay

share

Error Handling

catch

retry

retryWhen

Utility

do

delay

delayWhen

dematerialize

finally

let

materialize

observeOn

subscribeOn

timeInterval

timestamp

timeout

timeoutWith

toArray

toPromise

Conditional

and Boolean

defaultIfEmpty

every

find

findIndex

isEmpty

Mathematical

and Aggregate

count

max

min

reduce

Creation

ajax

bindCallback

bindNodeCallback

create

defer

empty

from

fromEvent

fromEventPattern

fromPromise

generate

interval

never

of

repeat

repeatWhen

range

throw

timer

Transformation

buffer

bufferCount

bufferTime

bufferToggle

bufferWhen

concatMap

concatMapTo

exhaustMap

expand

groupBy

map

mapTo

mergeMap

mergeMapTo

mergeScan

pairwise

partition

pluck

scan

switchMap

switchMapTo

window

windowCount

windowTime

windowToggle

windowWhen

Filtering

debounce

debounceTime

distinct

distinctKey

distinctUntilChanged

distinctUntilKeyChanged

elementAt

filter

first

ignoreElements

audit

auditTime

last

sample

sampleTime

single

skip

skipLast

skipUntil

skipWhile

take

takeLast

takeUntil

takeWhile

throttle

throttleTime

59 of 105

Enter search term…

this.companies$ = this.searchText.valueChanges.pipe(

debounceTime(500),

distinctUntilChanged(),

switchMap(searchText => this.companyService.search(searchText)),

);

60 of 105

@Injectable()export class PeopleService {

constructor(private http: Http) { }

getPeople() {

return this.http.get(`http://swapi.co/api/people/`)

.map(response => response.json());

.subscribe(people => console.log(people));

}

}

61 of 105

@Component()export class SearchComponent implements OnInit {� searchControl = new FormControl();ngOnInit() {this.searchControl.valueChanges.subscribe(value => {// do something with value here});}}

62 of 105

ngOnInit() {this.route.params.pipe(

map(params => params['id'])

mergeMap(id => this.contactsService.getContact(id))

)

.subscribe(contact => this.contact = contact);

}

63 of 105

RxJS is a journey...

64 of 105

HTTP is not the best example of why to use observables over promises

65 of 105

Modern web development is asynchronous

RxJS takes some effort to fully understand, but it simplifies writing async code

RxJS is baked into Angular

Summary - RxJS

66 of 105

CRM - Module 12

STATE MANAGEMENT WITH NGRX

67 of 105

State management is complex and time consuming

68 of 105

CONTAINER COMPONENT

SERVICE A

SERVICE A

69 of 105

CONTAINER COMPONENT

SERVICE A

SERVICE A

PRESENTATIONAL COMPONENT

70 of 105

CONTAINER COMPONENT

SERVICE A

SERVICE A

PRESENTATIONAL COMPONENT

@Input/@Output

PRESENTATIONAL COMPONENT

@Input/@Output

71 of 105

CONTAINER COMPONENT

SERVICE A

SERVICE A

PRESENTATIONAL COMPONENT

@Input/@Output

PRESENTATIONAL COMPONENT

@Input/@Output

PRESENTATIONAL COMPONENT

@Input/@Output

SERVICE B

72 of 105

CONTAINER COMPONENT

SERVICE A

SERVICE A

PRESENTATIONAL COMPONENT

@Input/@Output

PRESENTATIONAL COMPONENT

@Input/@Output

PRESENTATIONAL COMPONENT

@Input/@Output

SERVICE B

CONTAINER

COMPONENT

SERVICE B

SERVICE A

SERVICE B

73 of 105

CONTAINER COMPONENT

SERVICE A

SERVICE A

PRESENTATIONAL COMPONENT

@Input/@Output

CONTAINER COMPONENT

PRESENTATIONAL COMPONENT

@Input/@Output

SERVICE B

CONTAINER

COMPONENT

SERVICE B

SERVICE A

SERVICE B

SERVICE A

74 of 105

CONTAINER COMPONENT

SERVICE A

SERVICE A

PRESENTATIONAL COMPONENT

@Input/@Output

CONTAINER COMPONENT

PRESENTATIONAL COMPONENT

@Input/@Output

SERVICE B

CONTAINER

COMPONENT

SERVICE B

SERVICE A

SERVICE B

SERVICE A

CONTAINER COMPONENT

SERVICE A

SERVICE B

75 of 105

CONTAINER COMPONENT

SERVICE A

SERVICE A

PRESENTATIONAL COMPONENT

@Input/@Output

CONTAINER COMPONENT

PRESENTATIONAL COMPONENT

@Input/@Output

SERVICE B

CONTAINER

COMPONENT

SERVICE B

SERVICE A

SERVICE B

SERVICE A

CONTAINER COMPONENT

SERVICE A

SERVICE B

SERVICE C

SERVICE D

SERVICE C

SERVICE D

76 of 105

CONTAINER COMPONENT

SERVICE A

SERVICE A

PRESENTATIONAL COMPONENT

@Input/@Output

CONTAINER COMPONENT

PRESENTATIONAL COMPONENT

@Input/@Output

SERVICE B

CONTAINER

COMPONENT

SERVICE B

SERVICE A

SERVICE B

SERVICE A

CONTAINER COMPONENT

SERVICE A

SERVICE B

SERVICE C

SERVICE D

SERVICE C

SERVICE D

77 of 105

CONTAINER COMPONENT

SERVICE A

SERVICE A

PRESENTATIONAL COMPONENT

@Input/@Output

CONTAINER COMPONENT

PRESENTATIONAL COMPONENT

@Input/@Output

SERVICE B

CONTAINER

COMPONENT

SERVICE B

SERVICE A

SERVICE B

SERVICE A

CONTAINER COMPONENT

SERVICE A

SERVICE B

SERVICE C

SERVICE D

SERVICE C

SERVICE D

78 of 105

CONTAINER COMPONENT

SERVICE A

SERVICE A

PRESENTATIONAL COMPONENT

@Input/@Output

CONTAINER COMPONENT

PRESENTATIONAL COMPONENT

@Input/@Output

SERVICE B

CONTAINER

COMPONENT

SERVICE B

SERVICE A

SERVICE B

SERVICE A

CONTAINER COMPONENT

SERVICE A

SERVICE B

SERVICE C

SERVICE D

SERVICE C

SERVICE D

79 of 105

CONTAINER COMPONENT

SERVICE A

SERVICE A

PRESENTATIONAL COMPONENT

@Input/@Output

CONTAINER COMPONENT

PRESENTATIONAL COMPONENT

@Input/@Output

SERVICE B

CONTAINER

COMPONENT

SERVICE B

SERVICE A

SERVICE B

SERVICE A

CONTAINER COMPONENT

SERVICE A

SERVICE B

SERVICE C

SERVICE D

SERVICE C

SERVICE D

80 of 105

CONTAINER COMPONENT

STORE

STORE

PRESENTATIONAL COMPONENT

@Input/@Output

CONTAINER COMPONENT

PRESENTATIONAL COMPONENT

@Input/@Output

CONTAINER

COMPONENT

STORE

STORE

CONTAINER COMPONENT

STORE

81 of 105

+

=

+

RxJS

redux Pattern

ngrx

Angular

ngrx supercharges the redux pattern with RxJS

@angularsuperpowers @BrendanSSW @Jean_SSW

82 of 105

Component

Store

Reducers

ACTIONS

SELECTORS

NEW STATE

{

type: 'DELETE_COMPANY',

payload: {id:1}

}

{

companies: [

{id:1, name:'SSW'},

{id:2, name:'Microsoft'}

],

contacts: [

{id:1, name:Duncan}

]

};

companies: [

{id:1, name:'SSW'},

{id:2, name:'Microsoft'}

];

{

companies: [

{id:2, name:'Microsoft'}

],

contacts: [

{id:1, name:Duncan}

]

};

companies: [

{id:2, name:'Microsoft'}

];

current state

new state

action

store state

83 of 105

Component

Store

Reducers

ACTIONS

SELECTORS

Effects

Services

ACTIONS

NEW STATE

{

type: 'DELETE_COMPANY',

payload: {id:1}

}

{

companies: [

{id:1, name:'SSW'},

{id:2, name:'Microsoft'}

],

contacts: [

{id:1, name:Duncan}

]

};

{

companies: [

{id:2, name:'Microsoft'}

],

contacts: [

{id:1, name:Duncan}

]

};

companies: [

{id:2, name:'Microsoft'}

];

new state

action

{

type: 'DELETE_COMPANY_SUCCESS',

payload: {id:1}

}

action

store state

84 of 105

85 of 105

86 of 105

87 of 105

88 of 105

89 of 105

90 of 105

91 of 105

92 of 105

93 of 105

94 of 105

ngrx

… or not

  • Unnecessary complexity for small apps
  • Learning curve
  • Boiler plate
  • Simplify complex apps
  • Better tooling and ecosystem
  • Performance
  • Easier to test

95 of 105

  • Use an OAuth2 server to get a token
  • Use HttpClient Interceptors to attach token to request headers
  • RouteGuards - inject guard code into router

Authentication

@angularsuperpowers @MattEightyAte @Jean_SSW

96 of 105

JavaScript SPA

ASP.NET Core WebAPI

Identity Server

Browser

@angularsuperpowers @MattEightyAte @Jean_SSW

97 of 105

JavaScript SPA

ASP.NET Core WebAPI

Identity Server

Browser

oidc-client.js

Login Form

OIDC client redirects browser to a login page on the Identity Server.

User Logs in.

@angularsuperpowers @MattEightyAte @Jean_SSW

98 of 105

ASP.NET Core WebAPI

Identity Server

Browser

oidc-client.js

Identity Server redirects back with an Authorization Token

Token is saved on the browser to LocalStorage

auth.html

Auth Token

@angularsuperpowers @MattEightyAte @Jean_SSW

99 of 105

JavaScript SPA

ASP.NET Core WebAPI

Identity Server

Browser

Send the Auth Token as a HTTP header with all API requests

The API server checks the token against the Identity Server

Http

Auth Token

@angularsuperpowers @MattEightyAte @Jean_SSW

100 of 105

Auth Service - token in LocalStorage

@angularsuperpowers @MattEightyAte @Jean_SSW

101 of 105

Http Interceptor - apply token to all requests

@angularsuperpowers @MattEightyAte @Jean_SSW

102 of 105

Route Guards

@angularsuperpowers @MattEightyAte @Jean_SSW

103 of 105

SSW Reward App !

Download the App from the store

Get your first 500 points 🔥😍

Get a smart coffee cup, MiBands, Google Nest...

104 of 105

Feedback

105 of 105

Thank you!