Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Angular Architectures with Signals
Search
Manfred Steyer
PRO
November 08, 2023
Programming
870
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Angular Architectures with Signals
Manfred Steyer
PRO
November 08, 2023
More Decks by Manfred Steyer
See All by Manfred Steyer
Generative UI & AI-Assistants for Your Angular Solutions
manfredsteyer
PRO
1
350
Generative UI & AI-Assistants for Your Angular Solutions
manfredsteyer
PRO
0
160
Nostalgia Meets Technology: Super Mario with TypeScript
manfredsteyer
PRO
0
240
Signal Forms: Details & Live Coding @enterJS 2026 in Mannheim
manfredsteyer
PRO
0
260
Strategic Design in the Frontend: Moduliths & Micro Frontends @DDDEurope
manfredsteyer
PRO
0
180
Agentic UI
manfredsteyer
PRO
0
260
Signal Forms: Beyond the Basics @ngBaguette 2026 in Paris
manfredsteyer
PRO
0
320
Agentic UI beyond Chats Architecture Patterns & Open Standards @ngMunich 05/2026
manfredsteyer
PRO
0
260
Agentic AI in the Frontend: Architectures with Open Standards @iJS London 2026
manfredsteyer
PRO
0
190
Other Decks in Programming
See All in Programming
Cloudflare is Agents
chimame
0
160
わからない話を追いかけたら、プログラミング言語を作る側にいた
ydah
3
490
今さら聞けない .NET CLI
htkym
0
190
変わらないものが、変わるものを決める — 意図駆動開発 × イベントソーシング × イミュータブル | What Doesn't Change Decides What Can — IDD × Event Sourcing × Immutability
tomohisa
0
1.6k
Google Apps Script で Ruby を動かす
kawahara
0
200
5分で問診!Composer セキュリティ健康診断
codmoninc
0
970
AI Readyの正体はデータマネジメントだ メダリオン2.0の最前線
freee
PRO
0
210
freeeにおけるEvalsの実践例の紹介
freee
PRO
0
110
Go 1.27 における memory allocation の高速化
andpad
0
160
<title><a id="</title>君はこのHTMLをパースできるか"></a></title> #雑LT_study
pizzacat83
0
140
為什麼你並不需要ViewModel / No, you don't need a ViewModel
lovee
1
490
jsmini JavaScript Engine を作ってみた話
yosuke_furukawa
PRO
0
320
Featured
See All Featured
Between Models and Reality
mayunak
4
390
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.7k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
950
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.6k
Scaling GitHub
holman
464
140k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.5k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.5k
Six Lessons from altMBA
skipperchong
29
4.4k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
400
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.7k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
380
Building Applications with DynamoDB
mza
96
7.2k
Transcript
@ManfredSteyer ManfredSteyer Angular Architectures with Signals
@ManfredSteyer Signal as Producer 4711 Consumer read set notify 4712
@ManfredSteyer flights = signal<Flight[]>([]); const flights = await this.flightService.findAsPromise(from, to);
this.flights.set(flights); <div *ngFor="let f of flights()"> <flight-card [item]="f" /> </div>
@ManfredSteyer Simple Reactive Building Block Fine-grained CD Zone-less CD Interop
with RxJS No need to unsubscribe
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer Manfred Steyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer @Injectable({ providedIn: 'root' }) export class FlightBookingFacade { […]
private _flights = signal<Flight[]>([]); readonly flights = this._flights.asReadonly(); async load(from: string, to: string) { const flights = await […]; this._flights.set(flights); } }
@ManfredSteyer @Injectable({ providedIn: 'root' }) export class FlightBookingFacade { […]
private _flights = signal<Flight[]>([]); readonly flights = this._flights.asReadonly(); async load(from: string, to: string) { const flights = await […]; this._flights.set(flights); } }
@ManfredSteyer @Injectable({ providedIn: 'root' }) export class FlightBookingFacade { […]
private _flights = signal<Flight[]>([]); readonly flights = this._flights.asReadonly(); private _from = signal('Hamburg'); readonly from = this._from.asReadonly(); private _to = signal('Graz'); readonly to = this._to.asReadonly(); […] }
@ManfredSteyer @Injectable({ providedIn: 'root' }) export class FlightBookingFacade { […]
private state = signal({ from: 'Hamburg', to: 'Graz', flights: [] as Flight[], […] }); […] }
@ManfredSteyer @Injectable({ providedIn: 'root' }) export class FlightBookingFacade { […]
private state = signal({ from: 'Hamburg', to: 'Graz', flights: [] as Flight[], […] }); readonly flights = computed(() => this.state().flights); readonly from = computed(() => this.state().from); […] }
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer select(selector) selectSignal(selector)
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer @Injectable({ providedIn: 'root' }) export class FlightBookingFacade { private
state = signalState({ from: 'Paris', to: 'London', flights: [] as Flight[], basket: {} as Record<number, boolean>, }); readonly flights = this.state.flights; readonly from = this.state.from; […] }
@ManfredSteyer @Injectable({ providedIn: 'root' }) export class FlightBookingFacade { […]
readonly selected = computed( () => this.flights().filter((f) => this.basket()[f.id]) ); […] }
@ManfredSteyer @Injectable({ providedIn: 'root' }) export class FlightBookingFacade { […]
updateCriteria(from: string, to: string): void { patchState(this.state, { from, to }) } […] }
@ManfredSteyer @Injectable({ providedIn: 'root' }) export class FlightBookingFacade { […]
updateCriteria(from: string, to: string): void { patchState(this.state, (state) => ({ from, to })); } […] }
@ManfredSteyer @Injectable({ providedIn: 'root' }) export class FlightBookingFacade { […]
updateCriteria(from: string, to: string): void { patchState(this.state, updateRoute(from, to)); } […] } function updateRoute<T>(from: string, to: string) { return (state: T) => ({ from, to }) }
@ManfredSteyer private state = signalState({ filter: { from: 'Paris', to:
'London', }, flights: [] as Flight[], basket: {} as Record<number, boolean>, }); filter = this.state.filter(); from = this.state.filter.from(); to = this.state.filter.to();
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer export const FlightBookingStore = signalStore( { providedIn: 'root' },
[…] );
@ManfredSteyer export const FlightBookingStore = signalStore( { providedIn: 'root' },
withState({ from: 'Paris', to: 'London', […] }), […] );
@ManfredSteyer export const FlightBookingStore = signalStore( { providedIn: 'root' },
withState({ from: 'Paris', to: 'London', […] }), withComputed(([…]) => ({ […] })), withMethods(([…]) => ({ })), withHooks({ […] }) );
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer export const FlightBookingStore = signalStore( […] withMethods((state) => {
[…] return { connectCriteria: rxMethod<Criteria>((c$) => c$.pipe([…])) }; }), […] );
@ManfredSteyer export const FlightBookingStore = signalStore( […] withMethods((state) => {
[…] return { connectCriteria: rxMethod<Criteria>((c$) => c$.pipe([…])) }; }), […] );
@ManfredSteyer export const FlightBookingStore = signalStore( […] withMethods((state) => {
[…] return { connectCriteria: rxMethod<Criteria>((c$) => c$.pipe( filter(c => c.from.length >= 3 && c.to.length >= 3), debounceTime(300), switchMap((c) => flightService.find(c.from, c.to)), tap(flights => patchState(state, { flights })) )) }; }), […] );
@ManfredSteyer export const FlightBookingStore = signalStore( […] withHooks({ onInit({ connectCriteria,
criteria }) { connectCriteria(criteria); }, }), ); takes: Signal<T>, Observable<T>, T
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer export const FlightBookingStore = signalStore( { providedIn: 'root' },
withState({ from: 'Paris', to: 'London', […] }), withSignals(([…]) => ({ […] })), withMethods(([…]) => ({ })), withHooks({ […] }), withCallState() );
@ManfredSteyer export const FlightBookingStore = signalStore( { providedIn: 'root' },
withState({ from: 'Paris', to: 'London', […] }), withSignals(([…]) => ({ […] })), withMethods(([…]) => ({ })), withHooks({ […] }), withCallState() );
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer const BooksStore = signalStore( withEntities<Book>({ collection: 'book' }), withEntities<Author>({
collection: 'author' }) );
@ManfredSteyer const BooksStore = signalStore( withLoadEntities<Book>(BookService), withLoadEntities<Author>(AuthorService), );
@ManfredSteyer Free eBook (5th Edition) ANGULARarchitects.io/book Module Federation & Nx
@ManfredSteyer Services + Signals NGRX NGRX Signal Store Different Flavors
rxMethod Custom Features
@ManfredSteyer d Slides & Examples Remote Company Workshops and Consulting
http://angulararchitects.io