SlideShare a Scribd company logo
Angular Meetup
Angular v16, May 2023
The Rise of Angular Signals
Angular 16
"The biggest release since the initial rollout of Angular"
Yaron Biton
Misterbit CTO
Who am I?
Coding Academy
Chief Instructor
Angular 16
This release has a significant impact
on any Angular team
Let's deep dive into
how to code modern Angular apps
• Anything web, end to end projects
• Tech companies and startups
• Consulting to management and dev teams
• Available on demand coders
https://www.misterbit.co.il
• Advanced web-techs training: Angular, React,
Vue, Node, Modern architectures, etc.
• Catchup workshops for managers and leaders
• Coding Academy bootcamp
• Advanced selective training - best practices
• Hundreds of employed full-stack developers
every year
https://www.coding-academy.org
Angular 16 features
We can (finally) use self-enclosing-tags!
Becomes:
<super-duper-long-component-name [prop]="someVar">
</super-duper-long-component-name>
<super-duper-long-component-name [prop]="someVar"/>
Angular 16 features
We (finally) have a way to require a component
@Input:
Angular 16 features –
Rethinking NgModules
Tooling for standalone components, directives
and pipes
// The schematics convert an existing project
// remove unnecessary NgModules classes,
// and change the bootstrap of the project to use standalone APIs:
ng generate @angular/core:standalone
// new projects as standalone from the start:
ng new --standalone
// Creates a simpler project without any NgModules and with
// generators that produce standalone directives, components, and pipes
// Generate a standalone component
ng generate componenet --standalone cmpName
Rethinking the CLI –
(As most modern CLIs )
> ng serve
// Vite development server!
Angular CLI is now Vite!
Rethinking Unit-Testing
Moving Angular CLI to Jest
Rethinking Reactivity
Preface
• On February 2023, Angular's team introduced
Signals to the framework with a simple pull
request.
• Since then, there have been a storm in the Angular
community about its use and benefits
• …and if it’s another rewrite of the framework
• In a model-driven web application, one of the main jobs
of the framework is synchronizing changes to the
application's data model and the UI.
• We refer to this mechanism as reactivity, and every
modern web framework has its own reactivity system.
Reactivity with Signals
Welcome Signals
• In modern Angular every piece of important data is
wrapped and used as signals
• So, signals become immediately the most basic and
important feature in Angular
Signals
• Angular Signals have an initial
value
• When executed, they return the
current value of the signal
quantity_ = signal<number>(1)
selectedCar_ = signal<Car>(null)
userMsg_ = signal({ txt: '', type: '' })
cars_ = signal<Car[]>([])
<h5> Quantity: {{ quantity_() }} </h5>
<user-msg [msg]="userMsg_()"></user-msg>
Setting Signal value
The signal function returns a WritableSignal<T>
which allow modifying the value:
// Replace the signal value
const movies_ = signal<Movie[]>([])
movies_.set([{ name: 'Fight club' }])
// Derive a new value
const someCount_ = signal<Number>(0)
someCount_.update(n => n + 1)
// Perform internal mutation of arrays and other objects
movies_.mutate(list => {
list.push({name: 'Aba Ganuv'})
})
computed values
computed() creates a memoizing signal, which
calculates its value from some other signals
const counter_ = signal(0)
// Automatically updates when `counter` changes:
const isEven_ = computed(() => counter_() % 2 === 0)
The value of the computed signal is being
recalculated whenever any of it's dependencies
changes.
computed() Signal
• The computed() function returns a Signal and not a
WritableSignal, which means it cannot be manually
modified (with set, update, or mutate)
• Instead, it is updated automatically whenever one
of its dependent signals change.
export function computed<T>(
computation: () => T, equal: ValueEqualityFn<T> = defaultEquals): Signal<T>
const moviesCount_ = computed(() => movies_().length)
side effect()
effect() schedules and runs a side-effectful function
Signal dependencies of this function are captured,
and the side effect is re-executed whenever any of
its dependencies produces a new value.
const counter_ = signal(0)
effect(() => console.log('The counter is:', counter_()))
// The counter is: 0
counter_.set(1)
// The counter is: 1
Effects do not execute synchronously with the set but are scheduled and resolved by
the framework. The exact timing of effects is unspecified.
effect() use cases
Effects are useful in specific situations.
Here are some examples:
• Performing custom rendering to a <canvas>
• Charting library, or other third party UI
library
• Keeping data in sync with window.localStorage
Demo Time
Before going deeper let's play
with some sample code
effect() registration
• Registering a new effect with the effect() function
requires an "injection context" (access to the
inject function).
• So we call either:
• Create the effect within a constructor
• Assign the effect to a field
• Pass an Injector to effect via its options:
@Component({...})
export class EffectiveCounterCmp {
readonly count_ = signal(0)
constructor(private injector: Injector) {}
initializeLogging(): void {
effect(() => {
console.log(`The count is: ${this.count_()})`)
}, {injector: this.injector})
}
}
effect() registration caveat
Registering an effect in the wrong place, produces a
weird message:
ngOnInit() {
effect(() => console.log(JSON.stringify(this.cars_())))
}
Into Signals
• Signal is a reactive value and is a producer that
notify consumers(dependents) when it changes.
• Any code that has registered an interest in the
Signal’s value is tracked as dependent.
• When the Signal’s value is modified, the Signal
will notify all of its dependents, allowing them to
react to the change in the Signal’s value.
Adding dependents (consumer) to a Signal
• When we use a signal in our template, this
dependency is being added to that signal
• We can add consumers by using effect and computed
functions.
Signal effect destroy
• effects are automatically destroyed when their
enclosing context is destroyed
• The effect() function gets an onCleanup function and
returns an EffectRef, that can be used for manually
destroy
• destroy(): 🧹 Shut down the effect, removing it
from any upcoming scheduled executions.
• The signature of the effect function:
export function effect(
effectFn: () => EffectCleanupFn | void, options?: CreateEffectOptions): EffectRef
Signal equality functions
• When creating a signal, we can optionally provide
an equality function
• It will be used to check whether the new value is
actually different than the previous one
import _ from 'lodash'
const data_ = signal(['test'], {equal: _.isEqual})
// Using deep equality - signal won't trigger any updates
data_.set(['test'])
untracking
reading without tracking dependencies
// You can prevent a signal read from being tracked by calling its getter with untracked:
effect(() => {
console.log(`User set to `${ currentUser_() }` and the counter is ${untracked(counter_)}`)
})
// Another example - invoke some external code which shouldn't be treated as a dependency:
effect(() => {
const user = currentUser_()
untracked(() => {
// If the `loggingService` reads signals, they won't be counted as
// dependencies of this effect.
this.loggingService.log(`User set to ${user}`)
})
})
Into the RFC
Lets review some points
from the official docs
The downfall of Global,
top-down change detection
"Angular's default strategy is to run change detection
over the entire component tree to make sure that the
DOM reflects the most up-to-date model.
Because Angular has no information about which
parts of the application state have actually changed,
it must check everything.
In practice, however, only a fraction of the entire
application state changes and only a handful of
components need to be re-rendered."
The downfall of onPush
"While the OnPush strategy can reduce
some of the performance cost, this
strategy is (very) limited:
change detection always starts from the root component
Additionally - OnPush components prevent their
descendants from being checked, descendent components
that depend on global state are not updated."
The downfall of the single traversal
"Angular's change detection was designed to refresh
application state once. The change detection process starts
from the root of the component tree and walks all components
down to the leaf nodes.
However, many common web interaction patterns roll up
descendant node states into ancestor nodes (e.g. form validity
is computed as a function of descendant control states).
This leads to the most "popular" error in Angular -
ExpressionChangedAfterItHasBeenCheckedError."
The downfall of Zone.js
"Crucially, zone.js does not provide "fine-grained"
information about changes in the model.
Zone.js is only capable of notifying us when
something might have happened in the application,
and can give no information about what happened or
what has changed."
The downfall of Zone.js
• "Large applications often grow to see
zone.js become a source of performance
issues and developer-facing complexity.
• As the web platform continues to evolve, it
also represents a rising maintenance cost
for the Angular team."
The downfall of Zone.js
Zone Pollution
https://angular.io/guide/change-detection-zone-pollution
@Component(...)
class AppComponent {
constructor(private ngZone: NgZone) { }
ngOnInit() {
this.ngZone.runOutsideAngular(() => {
// Sometimes we need to skip running change detection:
Plotly.newPlot('chart', data)
})
}
}
The downfall of Zone.js
async – await?...
WARNING: Zone.js does not support native async/await.
These blocks are not intercepted by zone.js and
will not trigger change detection.
See: https://github.com/angular/zone.js/pull/1140 for more information.
What about RxJS?
RxJS remains in HttpClient
The good side:
Makes it easy to design asycn patterns such as keeping one request per input
trigger (switchMap) or piping into other Rxjs operators
Which http calls should be made in parallel (`mergeMap`), cancel the one
ongoing and move to the new one (`switchMap`), make one after another has
finished (`concatMap`), etc etc.
The bad side:
Setting up streams for one-time ajax calls
RxJS Interop - takeUntilDestroy
It is very common to tie the lifecycle of an Observable to a
particular component’s lifecycle
// Here is a common Angular pattern:
destroyed$ = new ReplaySubject<void>(1)
data$ = http.get('...').pipe(takeUntil(this.destroyed$))
ngOnDestroy() {
this.destroyed$.next()
}
// Now, we can:
data$ = http.get('…').pipe(takeUntilDestroyed())
RxJS Interop
Convert a signal to observable:
import { toObservable, signal } from '@angular/core/rxjs-interop'
@Component({ ...})
export class App {
count_ = signal(0)
count$ = toObservable(this.count_)
ngOnInit() {
this.count$.subscribe(() => ...)
}
}
RxJS Interop
Convert an observable to a signal:
import { toSignal } from '@angular/core/rxjs-interop'
@Component({
template: `
<li *ngFor="let row of data_()"> {{ row }} </li>
`
})
export class App {
dataService = inject(DataService)
data_ = toSignal(this.dataService.data$, [])
}
Promise => Observable => Signal someone?
Simple counter signal
Here is a simple counter signal
@Component({
template: `
<div>Count: {{ count_() }}</div>
<div>Double: {{ doubleCount_() }}</div>
`
})
export class App {
count_ = signal(0)
doubleCount_ = computed(() => this.count_() * 2)
constructor() {
setInterval(() => this.count_.set(this.count_() + 1), 1000)
}
}
Simple RxJS counter
import { BehaviorSubject, map, take } from 'rxjs'
export class AppComponent {
template: `
<div>Count: {{ count$ | async }}</div>
<div>Double: {{ doubledCount$ | async }}</div>
`,
count$ = timer(0, 1000)
doubleCount$ = this.count$.pipe(map((v) => v * 2))
}
Here is a simple counter with RxJS:
RxJS is hard for humans
RxJS has a still learning curve, some developers would code it like that:
import { BehaviorSubject, map, take } from 'rxjs'
@Component({
selector: 'counter',
template: `
<div>Count: {{ count$ | async }}</div>
<div>Double: {{ doubleCount$ | async }}</div>
`
})
export class AppComponent {
count$ = new BehaviorSubject(0)
doubleCount$ = this.count$.pipe(map((value) => value * 2))
constructor() {
setInterval(() => {
let currentCount = 0
this.count$.pipe(take(1)).subscribe((x) => (currentCount = x))
this.count$.next(currentCount + 1)
}, 1000)
}
}
The downfall of Rxjs
• "Angular does not internally use RxJS to
propagate state or drive rendering in any
way.
• Angular only uses RxJS as a convenient
EventEmitter completely disconnected from
the change detection and rendering system"
• Amm.. what about async pipes?..
The downfall of Rxjs
RxJS is not glitch-free - It's easy to craft an example which shows this behavior:
import { BehaviorSubject, combineLatest, map } from 'rxjs'
const counter$ = new BehaviorSubject(0)
const isEven$ = counter$.pipe(map((value) => value % 2 === 0))
const message$ = combineLatest(
[counter$, isEven$],
(counter, isEven) => `${counter} is ${isEven ? 'even' : 'odd'}`
)
message$.subscribe(console.log)
counter$.next(1)
// 0 is even
// 1 is even ???
// 1 is odd
In asynchronous RxJS code, glitches are not typically an
issue because async operations naturally resolve at
different times.
Most template operations, however, are synchronous, and
inconsistent intermediate results can have drastic
consequences for the UI.
For example, an NgIf may become true before the data is
actually ready
The downfall of Rxjs
"Signals replace the currently used BehaviorSubject
With Signals, Subscriptions get created and destroyed
automatically under the hood. More or less what happens
using the async pipe in RxJS.
However, unlike Observables, Signals don’t require a
Subscription to be used outside the template."
The downfall of Rxjs
"Using the async pipe several times creates separate
Subscriptions and separate HTTP requests.
Developers need to be conscious about using a
shareReplay or avoid multiple subscribers to avoid
multiple calls and side effects.
The downfall of Immutability
"Signals work with both, we don't want to "pick sides" but
rather let developers choose the approach that works
best for their teams and use-cases.
Signal-based Components
@Component({
signals: true,
selector: 'user-profile',
template: `
<p>Name: {{ firstName_() }} {{ lastName_() }}</p>
<p>Account suspended: {{ suspended_() }}</p>
`,
})
export class UserProfile {
firstName_ = input<string>() // Signal<string|undefined>
lastName_ = input('Smith') // Signal<string>
suspended_ = input<boolean>(false, {
alias: 'disabled',
})}
Upcoming
Model inputs and two-ways-data-binding
@Component({
signals: true,
selector: 'some-checkbox',
template: `
<p>Checked: {{ checked() }}</p>
<button (click)="toggle()">Toggle</button>
`,
})
export class SomeCheckbox {
// Create a *writable* signal.
checked_ = model(false)
toggle() {
checked_.update(c => !c)
}
}
Model inputs and two-ways-data-binding
@Component({
signals: true,
selector: 'some-page',
template: `
<!-- Note that the getter is *not* called here,
the raw signal is passed -->
<some-checkbox [(checked)]="isAdmin_" />
`,
})
export class SomePage {
isAdmin_ = signal(false)
}
Outputs in signal-based components
@Component({
signals: true,
selector: 'simple-counter',
template: `
<button (click)="save()">Save</button>
<button (click)="reset()">Reset</button>
`,
})
export class SimpleCounter {
saved = output<number>() // EventEmitter<number>
cleared = output<number>({alias: 'reset'})
save() {
this.saved.emit(123)
}
reset() {
this.cleared.emit(456)
}
}
Signal based queries
@Component({
signals: true,
selector: 'form-field',
template: `
<field-icon *ngFor="let icon of icons()"> {{ icon }} </field-icon>
<div class="focus-outline">
<input #field>
</div>
`
})
export class FormField {
icons = viewChildren(FieldIcon) // Signal<FieldIcon[]>
input = viewChild<ElementRef>('field') // Signal<ElementRef>
someEventHandler() {
this.input().nativeElement.focus()
}
}
Life cycle hooks
• Zone-based components support eight different lifecycle
methods.
• Many of these methods are tightly coupled to the current
change detection model, and don't make sense for signal-
based components.
• Signal-based components will retain the following lifecycle
methods:
• ngOnInit
• ngOnDestroy
Life cycle hooks
To supplement signal components, three new
application-level lifecycle hooks:
function afterNextRender(fn: () => void): void
function afterRender(fn: () => void): {destroy(): void}
function afterRenderEffect(fn: () => void): {destroy(): void}
* Why not ChangeDetectionStrategy.Signals?..
Life cycle hooks
Here is an example:
@Component({
template: `
<p #p>{{ longText_() }}</p>
`,
})
export class AfterRenderCmp {
constructor() {
afterNextRender(() => {
console.log('text height: ' + p_().nativeElement.scrollHeight)
})
}
p_ = viewQuery('p')
}
Is this another Angular rewrite?
Hmmm…. yes
The Angular team takes backwards compatibility seriously
But many things change in the surface API
Don’t rush: While many library developers will work on signal support
we gonna dance the semver for some time
Consider Microfrontends where applicable
• Available on demand coders
• Advanced web-techs training
• Consulting and workshops for leaders
Contact us:
admin@misterbit.co.il
https://www.misterbit.co.il
https://www.coding-academy.org
Know anyone that is a good fit?
send'em our way!

More Related Content

What's hot

Angular
AngularAngular
Angular Observables & RxJS Introduction
Angular Observables & RxJS IntroductionAngular Observables & RxJS Introduction
Angular Observables & RxJS Introduction
Rahat Khanna a.k.a mAppMechanic
 
Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJS
Brainhub
 
RxJS & Angular Reactive Forms @ Codemotion 2019
RxJS & Angular Reactive Forms @ Codemotion 2019RxJS & Angular Reactive Forms @ Codemotion 2019
RxJS & Angular Reactive Forms @ Codemotion 2019
Fabio Biondi
 
Introduction to angular with a simple but complete project
Introduction to angular with a simple but complete projectIntroduction to angular with a simple but complete project
Introduction to angular with a simple but complete project
Jadson Santos
 
What’s New in Angular 14?
What’s New in Angular 14?What’s New in Angular 14?
What’s New in Angular 14?
Albiorix Technology
 
Angular
AngularAngular
Angular Lifecycle Hooks
Angular Lifecycle HooksAngular Lifecycle Hooks
Angular Lifecycle Hooks
Squash Apps Pvt Ltd
 
Angular - Chapter 1 - Introduction
 Angular - Chapter 1 - Introduction Angular - Chapter 1 - Introduction
Angular - Chapter 1 - Introduction
WebStackAcademy
 
Angular App Presentation
Angular App PresentationAngular App Presentation
Angular App Presentation
Elizabeth Long
 
Routing & Navigating Pages in Angular 2
Routing & Navigating Pages in Angular 2Routing & Navigating Pages in Angular 2
Routing & Navigating Pages in Angular 2
Knoldus Inc.
 
Angular state Management-NgRx
Angular state Management-NgRxAngular state Management-NgRx
Angular state Management-NgRx
Knoldus Inc.
 
Angular - Chapter 3 - Components
Angular - Chapter 3 - ComponentsAngular - Chapter 3 - Components
Angular - Chapter 3 - Components
WebStackAcademy
 
Unit 1 - TypeScript & Introduction to Angular CLI.pptx
Unit 1 - TypeScript & Introduction to Angular CLI.pptxUnit 1 - TypeScript & Introduction to Angular CLI.pptx
Unit 1 - TypeScript & Introduction to Angular CLI.pptx
Malla Reddy University
 
Angular introduction students
Angular introduction studentsAngular introduction students
Angular introduction students
Christian John Felix
 
Angular - Chapter 5 - Directives
 Angular - Chapter 5 - Directives Angular - Chapter 5 - Directives
Angular - Chapter 5 - Directives
WebStackAcademy
 
Angular Advanced Routing
Angular Advanced RoutingAngular Advanced Routing
Angular Advanced Routing
Laurent Duveau
 
Angular Directives | Angular 2 Custom Directives | Angular Tutorial | Angular...
Angular Directives | Angular 2 Custom Directives | Angular Tutorial | Angular...Angular Directives | Angular 2 Custom Directives | Angular Tutorial | Angular...
Angular Directives | Angular 2 Custom Directives | Angular Tutorial | Angular...
Edureka!
 
Angular modules in depth
Angular modules in depthAngular modules in depth
Angular modules in depth
Christoffer Noring
 
Angular and The Case for RxJS
Angular and The Case for RxJSAngular and The Case for RxJS
Angular and The Case for RxJS
Sandi Barr
 

What's hot (20)

Angular
AngularAngular
Angular
 
Angular Observables & RxJS Introduction
Angular Observables & RxJS IntroductionAngular Observables & RxJS Introduction
Angular Observables & RxJS Introduction
 
Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJS
 
RxJS & Angular Reactive Forms @ Codemotion 2019
RxJS & Angular Reactive Forms @ Codemotion 2019RxJS & Angular Reactive Forms @ Codemotion 2019
RxJS & Angular Reactive Forms @ Codemotion 2019
 
Introduction to angular with a simple but complete project
Introduction to angular with a simple but complete projectIntroduction to angular with a simple but complete project
Introduction to angular with a simple but complete project
 
What’s New in Angular 14?
What’s New in Angular 14?What’s New in Angular 14?
What’s New in Angular 14?
 
Angular
AngularAngular
Angular
 
Angular Lifecycle Hooks
Angular Lifecycle HooksAngular Lifecycle Hooks
Angular Lifecycle Hooks
 
Angular - Chapter 1 - Introduction
 Angular - Chapter 1 - Introduction Angular - Chapter 1 - Introduction
Angular - Chapter 1 - Introduction
 
Angular App Presentation
Angular App PresentationAngular App Presentation
Angular App Presentation
 
Routing & Navigating Pages in Angular 2
Routing & Navigating Pages in Angular 2Routing & Navigating Pages in Angular 2
Routing & Navigating Pages in Angular 2
 
Angular state Management-NgRx
Angular state Management-NgRxAngular state Management-NgRx
Angular state Management-NgRx
 
Angular - Chapter 3 - Components
Angular - Chapter 3 - ComponentsAngular - Chapter 3 - Components
Angular - Chapter 3 - Components
 
Unit 1 - TypeScript & Introduction to Angular CLI.pptx
Unit 1 - TypeScript & Introduction to Angular CLI.pptxUnit 1 - TypeScript & Introduction to Angular CLI.pptx
Unit 1 - TypeScript & Introduction to Angular CLI.pptx
 
Angular introduction students
Angular introduction studentsAngular introduction students
Angular introduction students
 
Angular - Chapter 5 - Directives
 Angular - Chapter 5 - Directives Angular - Chapter 5 - Directives
Angular - Chapter 5 - Directives
 
Angular Advanced Routing
Angular Advanced RoutingAngular Advanced Routing
Angular Advanced Routing
 
Angular Directives | Angular 2 Custom Directives | Angular Tutorial | Angular...
Angular Directives | Angular 2 Custom Directives | Angular Tutorial | Angular...Angular Directives | Angular 2 Custom Directives | Angular Tutorial | Angular...
Angular Directives | Angular 2 Custom Directives | Angular Tutorial | Angular...
 
Angular modules in depth
Angular modules in depthAngular modules in depth
Angular modules in depth
 
Angular and The Case for RxJS
Angular and The Case for RxJSAngular and The Case for RxJS
Angular and The Case for RxJS
 

Similar to Angular 16 – the rise of Signals

Commit University - Exploring Angular 2
Commit University - Exploring Angular 2Commit University - Exploring Angular 2
Commit University - Exploring Angular 2
Commit University
 
Developing maintainable Cordova applications
Developing maintainable Cordova applicationsDeveloping maintainable Cordova applications
Developing maintainable Cordova applications
Ivano Malavolta
 
devjam2018 - angular 5 performance
devjam2018  - angular 5 performancedevjam2018  - angular 5 performance
devjam2018 - angular 5 performance
Elad Hirsch
 
Angular performance slides
Angular performance slidesAngular performance slides
Angular performance slides
David Barreto
 
From User Action to Framework Reaction
From User Action to Framework ReactionFrom User Action to Framework Reaction
From User Action to Framework Reaction
Jonas Bandi
 
Angular Js Basics
Angular Js BasicsAngular Js Basics
Angular Js Basics
أحمد عبد الوهاب
 
Declarative presentations UIKonf
Declarative presentations UIKonfDeclarative presentations UIKonf
Declarative presentations UIKonf
Nataliya Patsovska
 
Taming event-driven software via formal verification
Taming event-driven software via formal verificationTaming event-driven software via formal verification
Taming event-driven software via formal verification
AdaCore
 
From User Action to Framework Reaction
From User Action to Framework ReactionFrom User Action to Framework Reaction
From User Action to Framework Reaction
jbandi
 
Angular2 with type script
Angular2 with type scriptAngular2 with type script
Angular2 with type script
Ravi Mone
 
Angular Optimization Web Performance Meetup
Angular Optimization Web Performance MeetupAngular Optimization Web Performance Meetup
Angular Optimization Web Performance Meetup
David Barreto
 
Angular meetup 2 2019-08-29
Angular meetup 2   2019-08-29Angular meetup 2   2019-08-29
Angular meetup 2 2019-08-29
Nitin Bhojwani
 
AngularJs Crash Course
AngularJs Crash CourseAngularJs Crash Course
AngularJs Crash Course
Keith Bloomfield
 
Workshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte IIWorkshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte II
Visual Engineering
 
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
VitaliyMakogon
 
Angularjs Basics
Angularjs BasicsAngularjs Basics
Angularjs Basics
Anuradha Bandara
 
Top 7 Angular Best Practices to Organize Your Angular App
Top 7 Angular Best Practices to Organize Your Angular AppTop 7 Angular Best Practices to Organize Your Angular App
Top 7 Angular Best Practices to Organize Your Angular App
Katy Slemon
 
Angular workshop - Full Development Guide
Angular workshop - Full Development GuideAngular workshop - Full Development Guide
Angular workshop - Full Development Guide
Nitin Giri
 
Kogito: cloud native business automation
Kogito: cloud native business automationKogito: cloud native business automation
Kogito: cloud native business automation
Mario Fusco
 

Similar to Angular 16 – the rise of Signals (20)

Commit University - Exploring Angular 2
Commit University - Exploring Angular 2Commit University - Exploring Angular 2
Commit University - Exploring Angular 2
 
Angular js
Angular jsAngular js
Angular js
 
Developing maintainable Cordova applications
Developing maintainable Cordova applicationsDeveloping maintainable Cordova applications
Developing maintainable Cordova applications
 
devjam2018 - angular 5 performance
devjam2018  - angular 5 performancedevjam2018  - angular 5 performance
devjam2018 - angular 5 performance
 
Angular performance slides
Angular performance slidesAngular performance slides
Angular performance slides
 
From User Action to Framework Reaction
From User Action to Framework ReactionFrom User Action to Framework Reaction
From User Action to Framework Reaction
 
Angular Js Basics
Angular Js BasicsAngular Js Basics
Angular Js Basics
 
Declarative presentations UIKonf
Declarative presentations UIKonfDeclarative presentations UIKonf
Declarative presentations UIKonf
 
Taming event-driven software via formal verification
Taming event-driven software via formal verificationTaming event-driven software via formal verification
Taming event-driven software via formal verification
 
From User Action to Framework Reaction
From User Action to Framework ReactionFrom User Action to Framework Reaction
From User Action to Framework Reaction
 
Angular2 with type script
Angular2 with type scriptAngular2 with type script
Angular2 with type script
 
Angular Optimization Web Performance Meetup
Angular Optimization Web Performance MeetupAngular Optimization Web Performance Meetup
Angular Optimization Web Performance Meetup
 
Angular meetup 2 2019-08-29
Angular meetup 2   2019-08-29Angular meetup 2   2019-08-29
Angular meetup 2 2019-08-29
 
AngularJs Crash Course
AngularJs Crash CourseAngularJs Crash Course
AngularJs Crash Course
 
Workshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte IIWorkshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte II
 
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
 
Angularjs Basics
Angularjs BasicsAngularjs Basics
Angularjs Basics
 
Top 7 Angular Best Practices to Organize Your Angular App
Top 7 Angular Best Practices to Organize Your Angular AppTop 7 Angular Best Practices to Organize Your Angular App
Top 7 Angular Best Practices to Organize Your Angular App
 
Angular workshop - Full Development Guide
Angular workshop - Full Development GuideAngular workshop - Full Development Guide
Angular workshop - Full Development Guide
 
Kogito: cloud native business automation
Kogito: cloud native business automationKogito: cloud native business automation
Kogito: cloud native business automation
 

Recently uploaded

Explore Modern SharePoint Templates for 2024
Explore Modern SharePoint Templates for 2024Explore Modern SharePoint Templates for 2024
Explore Modern SharePoint Templates for 2024
Sharepoint Designs
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
Software Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdfSoftware Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdf
MayankTawar1
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
AMB-Review
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Hivelance Technology
 
Why React Native as a Strategic Advantage for Startup Innovation.pdf
Why React Native as a Strategic Advantage for Startup Innovation.pdfWhy React Native as a Strategic Advantage for Startup Innovation.pdf
Why React Native as a Strategic Advantage for Startup Innovation.pdf
ayushiqss
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
informapgpstrackings
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
IES VE
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar
 
Visitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.appVisitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.app
NaapbooksPrivateLimi
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
Tendenci - The Open Source AMS (Association Management Software)
 
Designing for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web ServicesDesigning for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web Services
KrzysztofKkol1
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
Globus
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
Tier1 app
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
vrstrong314
 

Recently uploaded (20)

Explore Modern SharePoint Templates for 2024
Explore Modern SharePoint Templates for 2024Explore Modern SharePoint Templates for 2024
Explore Modern SharePoint Templates for 2024
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
Software Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdfSoftware Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdf
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
 
Why React Native as a Strategic Advantage for Startup Innovation.pdf
Why React Native as a Strategic Advantage for Startup Innovation.pdfWhy React Native as a Strategic Advantage for Startup Innovation.pdf
Why React Native as a Strategic Advantage for Startup Innovation.pdf
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
Visitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.appVisitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.app
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
 
Designing for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web ServicesDesigning for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web Services
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 

Angular 16 – the rise of Signals

  • 1. Angular Meetup Angular v16, May 2023 The Rise of Angular Signals
  • 2. Angular 16 "The biggest release since the initial rollout of Angular"
  • 3. Yaron Biton Misterbit CTO Who am I? Coding Academy Chief Instructor
  • 4. Angular 16 This release has a significant impact on any Angular team Let's deep dive into how to code modern Angular apps
  • 5. • Anything web, end to end projects • Tech companies and startups • Consulting to management and dev teams • Available on demand coders https://www.misterbit.co.il
  • 6. • Advanced web-techs training: Angular, React, Vue, Node, Modern architectures, etc. • Catchup workshops for managers and leaders • Coding Academy bootcamp • Advanced selective training - best practices • Hundreds of employed full-stack developers every year https://www.coding-academy.org
  • 7. Angular 16 features We can (finally) use self-enclosing-tags! Becomes: <super-duper-long-component-name [prop]="someVar"> </super-duper-long-component-name> <super-duper-long-component-name [prop]="someVar"/>
  • 8. Angular 16 features We (finally) have a way to require a component @Input:
  • 9. Angular 16 features – Rethinking NgModules Tooling for standalone components, directives and pipes // The schematics convert an existing project // remove unnecessary NgModules classes, // and change the bootstrap of the project to use standalone APIs: ng generate @angular/core:standalone // new projects as standalone from the start: ng new --standalone // Creates a simpler project without any NgModules and with // generators that produce standalone directives, components, and pipes // Generate a standalone component ng generate componenet --standalone cmpName
  • 10. Rethinking the CLI – (As most modern CLIs ) > ng serve // Vite development server! Angular CLI is now Vite!
  • 13. Preface • On February 2023, Angular's team introduced Signals to the framework with a simple pull request. • Since then, there have been a storm in the Angular community about its use and benefits • …and if it’s another rewrite of the framework
  • 14. • In a model-driven web application, one of the main jobs of the framework is synchronizing changes to the application's data model and the UI. • We refer to this mechanism as reactivity, and every modern web framework has its own reactivity system. Reactivity with Signals
  • 15. Welcome Signals • In modern Angular every piece of important data is wrapped and used as signals • So, signals become immediately the most basic and important feature in Angular
  • 16. Signals • Angular Signals have an initial value • When executed, they return the current value of the signal quantity_ = signal<number>(1) selectedCar_ = signal<Car>(null) userMsg_ = signal({ txt: '', type: '' }) cars_ = signal<Car[]>([]) <h5> Quantity: {{ quantity_() }} </h5> <user-msg [msg]="userMsg_()"></user-msg>
  • 17. Setting Signal value The signal function returns a WritableSignal<T> which allow modifying the value: // Replace the signal value const movies_ = signal<Movie[]>([]) movies_.set([{ name: 'Fight club' }]) // Derive a new value const someCount_ = signal<Number>(0) someCount_.update(n => n + 1) // Perform internal mutation of arrays and other objects movies_.mutate(list => { list.push({name: 'Aba Ganuv'}) })
  • 18. computed values computed() creates a memoizing signal, which calculates its value from some other signals const counter_ = signal(0) // Automatically updates when `counter` changes: const isEven_ = computed(() => counter_() % 2 === 0) The value of the computed signal is being recalculated whenever any of it's dependencies changes.
  • 19. computed() Signal • The computed() function returns a Signal and not a WritableSignal, which means it cannot be manually modified (with set, update, or mutate) • Instead, it is updated automatically whenever one of its dependent signals change. export function computed<T>( computation: () => T, equal: ValueEqualityFn<T> = defaultEquals): Signal<T> const moviesCount_ = computed(() => movies_().length)
  • 20. side effect() effect() schedules and runs a side-effectful function Signal dependencies of this function are captured, and the side effect is re-executed whenever any of its dependencies produces a new value. const counter_ = signal(0) effect(() => console.log('The counter is:', counter_())) // The counter is: 0 counter_.set(1) // The counter is: 1 Effects do not execute synchronously with the set but are scheduled and resolved by the framework. The exact timing of effects is unspecified.
  • 21. effect() use cases Effects are useful in specific situations. Here are some examples: • Performing custom rendering to a <canvas> • Charting library, or other third party UI library • Keeping data in sync with window.localStorage
  • 22. Demo Time Before going deeper let's play with some sample code
  • 23. effect() registration • Registering a new effect with the effect() function requires an "injection context" (access to the inject function). • So we call either: • Create the effect within a constructor • Assign the effect to a field • Pass an Injector to effect via its options: @Component({...}) export class EffectiveCounterCmp { readonly count_ = signal(0) constructor(private injector: Injector) {} initializeLogging(): void { effect(() => { console.log(`The count is: ${this.count_()})`) }, {injector: this.injector}) } }
  • 24. effect() registration caveat Registering an effect in the wrong place, produces a weird message: ngOnInit() { effect(() => console.log(JSON.stringify(this.cars_()))) }
  • 25. Into Signals • Signal is a reactive value and is a producer that notify consumers(dependents) when it changes. • Any code that has registered an interest in the Signal’s value is tracked as dependent. • When the Signal’s value is modified, the Signal will notify all of its dependents, allowing them to react to the change in the Signal’s value.
  • 26. Adding dependents (consumer) to a Signal • When we use a signal in our template, this dependency is being added to that signal • We can add consumers by using effect and computed functions.
  • 27. Signal effect destroy • effects are automatically destroyed when their enclosing context is destroyed • The effect() function gets an onCleanup function and returns an EffectRef, that can be used for manually destroy • destroy(): 🧹 Shut down the effect, removing it from any upcoming scheduled executions. • The signature of the effect function: export function effect( effectFn: () => EffectCleanupFn | void, options?: CreateEffectOptions): EffectRef
  • 28. Signal equality functions • When creating a signal, we can optionally provide an equality function • It will be used to check whether the new value is actually different than the previous one import _ from 'lodash' const data_ = signal(['test'], {equal: _.isEqual}) // Using deep equality - signal won't trigger any updates data_.set(['test'])
  • 29. untracking reading without tracking dependencies // You can prevent a signal read from being tracked by calling its getter with untracked: effect(() => { console.log(`User set to `${ currentUser_() }` and the counter is ${untracked(counter_)}`) }) // Another example - invoke some external code which shouldn't be treated as a dependency: effect(() => { const user = currentUser_() untracked(() => { // If the `loggingService` reads signals, they won't be counted as // dependencies of this effect. this.loggingService.log(`User set to ${user}`) }) })
  • 30. Into the RFC Lets review some points from the official docs
  • 31. The downfall of Global, top-down change detection "Angular's default strategy is to run change detection over the entire component tree to make sure that the DOM reflects the most up-to-date model. Because Angular has no information about which parts of the application state have actually changed, it must check everything. In practice, however, only a fraction of the entire application state changes and only a handful of components need to be re-rendered."
  • 32. The downfall of onPush "While the OnPush strategy can reduce some of the performance cost, this strategy is (very) limited: change detection always starts from the root component Additionally - OnPush components prevent their descendants from being checked, descendent components that depend on global state are not updated."
  • 33. The downfall of the single traversal "Angular's change detection was designed to refresh application state once. The change detection process starts from the root of the component tree and walks all components down to the leaf nodes. However, many common web interaction patterns roll up descendant node states into ancestor nodes (e.g. form validity is computed as a function of descendant control states). This leads to the most "popular" error in Angular - ExpressionChangedAfterItHasBeenCheckedError."
  • 34. The downfall of Zone.js "Crucially, zone.js does not provide "fine-grained" information about changes in the model. Zone.js is only capable of notifying us when something might have happened in the application, and can give no information about what happened or what has changed."
  • 35. The downfall of Zone.js • "Large applications often grow to see zone.js become a source of performance issues and developer-facing complexity. • As the web platform continues to evolve, it also represents a rising maintenance cost for the Angular team."
  • 36. The downfall of Zone.js Zone Pollution https://angular.io/guide/change-detection-zone-pollution @Component(...) class AppComponent { constructor(private ngZone: NgZone) { } ngOnInit() { this.ngZone.runOutsideAngular(() => { // Sometimes we need to skip running change detection: Plotly.newPlot('chart', data) }) } }
  • 37. The downfall of Zone.js async – await?... WARNING: Zone.js does not support native async/await. These blocks are not intercepted by zone.js and will not trigger change detection. See: https://github.com/angular/zone.js/pull/1140 for more information.
  • 39. RxJS remains in HttpClient The good side: Makes it easy to design asycn patterns such as keeping one request per input trigger (switchMap) or piping into other Rxjs operators Which http calls should be made in parallel (`mergeMap`), cancel the one ongoing and move to the new one (`switchMap`), make one after another has finished (`concatMap`), etc etc. The bad side: Setting up streams for one-time ajax calls
  • 40. RxJS Interop - takeUntilDestroy It is very common to tie the lifecycle of an Observable to a particular component’s lifecycle // Here is a common Angular pattern: destroyed$ = new ReplaySubject<void>(1) data$ = http.get('...').pipe(takeUntil(this.destroyed$)) ngOnDestroy() { this.destroyed$.next() } // Now, we can: data$ = http.get('…').pipe(takeUntilDestroyed())
  • 41. RxJS Interop Convert a signal to observable: import { toObservable, signal } from '@angular/core/rxjs-interop' @Component({ ...}) export class App { count_ = signal(0) count$ = toObservable(this.count_) ngOnInit() { this.count$.subscribe(() => ...) } }
  • 42. RxJS Interop Convert an observable to a signal: import { toSignal } from '@angular/core/rxjs-interop' @Component({ template: ` <li *ngFor="let row of data_()"> {{ row }} </li> ` }) export class App { dataService = inject(DataService) data_ = toSignal(this.dataService.data$, []) } Promise => Observable => Signal someone?
  • 43. Simple counter signal Here is a simple counter signal @Component({ template: ` <div>Count: {{ count_() }}</div> <div>Double: {{ doubleCount_() }}</div> ` }) export class App { count_ = signal(0) doubleCount_ = computed(() => this.count_() * 2) constructor() { setInterval(() => this.count_.set(this.count_() + 1), 1000) } }
  • 44. Simple RxJS counter import { BehaviorSubject, map, take } from 'rxjs' export class AppComponent { template: ` <div>Count: {{ count$ | async }}</div> <div>Double: {{ doubledCount$ | async }}</div> `, count$ = timer(0, 1000) doubleCount$ = this.count$.pipe(map((v) => v * 2)) } Here is a simple counter with RxJS:
  • 45. RxJS is hard for humans RxJS has a still learning curve, some developers would code it like that: import { BehaviorSubject, map, take } from 'rxjs' @Component({ selector: 'counter', template: ` <div>Count: {{ count$ | async }}</div> <div>Double: {{ doubleCount$ | async }}</div> ` }) export class AppComponent { count$ = new BehaviorSubject(0) doubleCount$ = this.count$.pipe(map((value) => value * 2)) constructor() { setInterval(() => { let currentCount = 0 this.count$.pipe(take(1)).subscribe((x) => (currentCount = x)) this.count$.next(currentCount + 1) }, 1000) } }
  • 46. The downfall of Rxjs • "Angular does not internally use RxJS to propagate state or drive rendering in any way. • Angular only uses RxJS as a convenient EventEmitter completely disconnected from the change detection and rendering system" • Amm.. what about async pipes?..
  • 47. The downfall of Rxjs RxJS is not glitch-free - It's easy to craft an example which shows this behavior: import { BehaviorSubject, combineLatest, map } from 'rxjs' const counter$ = new BehaviorSubject(0) const isEven$ = counter$.pipe(map((value) => value % 2 === 0)) const message$ = combineLatest( [counter$, isEven$], (counter, isEven) => `${counter} is ${isEven ? 'even' : 'odd'}` ) message$.subscribe(console.log) counter$.next(1) // 0 is even // 1 is even ??? // 1 is odd In asynchronous RxJS code, glitches are not typically an issue because async operations naturally resolve at different times. Most template operations, however, are synchronous, and inconsistent intermediate results can have drastic consequences for the UI. For example, an NgIf may become true before the data is actually ready
  • 48. The downfall of Rxjs "Signals replace the currently used BehaviorSubject With Signals, Subscriptions get created and destroyed automatically under the hood. More or less what happens using the async pipe in RxJS. However, unlike Observables, Signals don’t require a Subscription to be used outside the template."
  • 49. The downfall of Rxjs "Using the async pipe several times creates separate Subscriptions and separate HTTP requests. Developers need to be conscious about using a shareReplay or avoid multiple subscribers to avoid multiple calls and side effects.
  • 50. The downfall of Immutability "Signals work with both, we don't want to "pick sides" but rather let developers choose the approach that works best for their teams and use-cases.
  • 51. Signal-based Components @Component({ signals: true, selector: 'user-profile', template: ` <p>Name: {{ firstName_() }} {{ lastName_() }}</p> <p>Account suspended: {{ suspended_() }}</p> `, }) export class UserProfile { firstName_ = input<string>() // Signal<string|undefined> lastName_ = input('Smith') // Signal<string> suspended_ = input<boolean>(false, { alias: 'disabled', })} Upcoming
  • 52. Model inputs and two-ways-data-binding @Component({ signals: true, selector: 'some-checkbox', template: ` <p>Checked: {{ checked() }}</p> <button (click)="toggle()">Toggle</button> `, }) export class SomeCheckbox { // Create a *writable* signal. checked_ = model(false) toggle() { checked_.update(c => !c) } }
  • 53. Model inputs and two-ways-data-binding @Component({ signals: true, selector: 'some-page', template: ` <!-- Note that the getter is *not* called here, the raw signal is passed --> <some-checkbox [(checked)]="isAdmin_" /> `, }) export class SomePage { isAdmin_ = signal(false) }
  • 54. Outputs in signal-based components @Component({ signals: true, selector: 'simple-counter', template: ` <button (click)="save()">Save</button> <button (click)="reset()">Reset</button> `, }) export class SimpleCounter { saved = output<number>() // EventEmitter<number> cleared = output<number>({alias: 'reset'}) save() { this.saved.emit(123) } reset() { this.cleared.emit(456) } }
  • 55. Signal based queries @Component({ signals: true, selector: 'form-field', template: ` <field-icon *ngFor="let icon of icons()"> {{ icon }} </field-icon> <div class="focus-outline"> <input #field> </div> ` }) export class FormField { icons = viewChildren(FieldIcon) // Signal<FieldIcon[]> input = viewChild<ElementRef>('field') // Signal<ElementRef> someEventHandler() { this.input().nativeElement.focus() } }
  • 56. Life cycle hooks • Zone-based components support eight different lifecycle methods. • Many of these methods are tightly coupled to the current change detection model, and don't make sense for signal- based components. • Signal-based components will retain the following lifecycle methods: • ngOnInit • ngOnDestroy
  • 57. Life cycle hooks To supplement signal components, three new application-level lifecycle hooks: function afterNextRender(fn: () => void): void function afterRender(fn: () => void): {destroy(): void} function afterRenderEffect(fn: () => void): {destroy(): void} * Why not ChangeDetectionStrategy.Signals?..
  • 58. Life cycle hooks Here is an example: @Component({ template: ` <p #p>{{ longText_() }}</p> `, }) export class AfterRenderCmp { constructor() { afterNextRender(() => { console.log('text height: ' + p_().nativeElement.scrollHeight) }) } p_ = viewQuery('p') }
  • 59. Is this another Angular rewrite? Hmmm…. yes The Angular team takes backwards compatibility seriously But many things change in the surface API Don’t rush: While many library developers will work on signal support we gonna dance the semver for some time Consider Microfrontends where applicable
  • 60. • Available on demand coders • Advanced web-techs training • Consulting and workshops for leaders Contact us: admin@misterbit.co.il https://www.misterbit.co.il https://www.coding-academy.org Know anyone that is a good fit? send'em our way!