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
Modern Angular: Architectures with Standalone C...
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Manfred Steyer
PRO
February 22, 2023
Programming
810
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Modern Angular: Architectures with Standalone Components
Manfred Steyer
PRO
February 22, 2023
More Decks by Manfred Steyer
See All by Manfred Steyer
Signal Forms: Details & Live Coding @enterJS 2026 in Mannheim
manfredsteyer
PRO
0
97
Strategic Design in the Frontend: Moduliths & Micro Frontends @DDDEurope
manfredsteyer
PRO
0
93
Agentic UI
manfredsteyer
PRO
0
140
Signal Forms: Beyond the Basics @ngBaguette 2026 in Paris
manfredsteyer
PRO
0
240
Agentic UI beyond Chats Architecture Patterns & Open Standards @ngMunich 05/2026
manfredsteyer
PRO
0
220
Agentic AI in the Frontend: Architectures with Open Standards @iJS London 2026
manfredsteyer
PRO
0
150
Agentic AI & UI: Arcitecture, HITL, Emerging Standards
manfredsteyer
PRO
0
180
Agentic UI Requires Standards: AG-UI, A2UI, and MCP Apps Work Together @Angular London
manfredsteyer
PRO
1
97
Signal Forms: Beyond the Basics @ngBelgrade 2026
manfredsteyer
PRO
0
220
Other Decks in Programming
See All in Programming
並列実装の現場、2ヶ月間実務でAIを使い倒したAIもPCも私も限界が近い
ming_ayami
0
120
Lemonade + Foundry Toolkit でお手軽アプリ開発
seosoft
1
320
ローカルLLMを使ってB2Bサービスを作っていての学び
yaotti
0
160
キャリア迷子上等 ─ "ない道"は自分で作ればいい
16bitidol
3
2k
セキュリティの専門家じゃなくてもできる。「セキュリティ意識」をアップデートして サプライチェーン攻撃への耐性を高めよう。
tk3fftk
5
710
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
690
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.6k
生成AI時代にこそ効くGo | Why Go Works in the Age of Generative AI
mom0tomo
8
3.2k
RTSPクライアントを自作してみた話
simotin13
0
570
Vue × Nuxt × Oxc どこまで使える?実運用の現在地
andpad
0
210
Spring Security 実践 ─ GraphQL APIで実務に役立つ 認証・認可 を学ぶ
wagyu
0
220
依存関係から依存物へ―Dependencyという言葉の歴史をひも解く
j_lee
0
110
Featured
See All Featured
Between Models and Reality
mayunak
4
330
Speed Design
sergeychernyshev
33
1.8k
Paper Plane (Part 1)
katiecoart
PRO
0
8.8k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.8k
Utilizing Notion as your number one productivity tool
mfonobong
4
320
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
1
2k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.3k
How to train your dragon (web standard)
notwaldorf
97
6.7k
エンジニアに許された特別な時間の終わり
watany
107
250k
Bash Introduction
62gerente
615
220k
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
610
Product Roadmaps are Hard
iamctodd
PRO
55
12k
Transcript
@ManfredSteyer Modern Angular: Architectures with Standalone Components ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer Manfred Steyer
@ManfredSteyer
@ManfredSteyer NgModules + EcmaScript Modules import { NgModule } from
'@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; […] @NgModule({ imports: [BrowserModule, OtherModule], declarations: [AppComponent, OtherComponent, OtherDirective], providers: [], bootstrap: [AppComponent], }) export class AppModule {} TypeScript Modules Angular Modules
@ManfredSteyer @Component({ standalone: true, imports: [ […], FlightCardComponent, CityPipe, CityValidator,
], selector: 'flight-search', templateUrl: '…' }) export class FlightSearchComponent { […] }
@ManfredSteyer @Component({ standalone: true, imports: [ […], FlightCardComponent, CityPipe, CityValidator,
], selector: 'flight-search', templateUrl: '…' }) export class FlightSearchComponent { […] }
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer Small and Medium Apps: Folder per Feature
@ManfredSteyer Medium and Large Apps: Folder per Domain
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer → @Component({ standalone: true, selector: 'app-root', imports: [ […]
TicketsModule, ], templateUrl: '…' }) export class AppComponent { }
@ManfredSteyer → @Component({ standalone: true, selector: 'app-root', imports: [ […]
TicketsModule, ], templateUrl: '…' }) export class AppComponent { }
@ManfredSteyer → @NgModule({ imports: [ FlightCardComponent, ], declarations: [ MyTicketsComponent
], }) export class TicketsModule { }
@ManfredSteyer → @NgModule({ imports: [ FlightCardComponent, ], declarations: [ MyTicketsComponent
], }) export class TicketsModule { }
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ MyGlobalService, importProvidersFrom(MyModule), ] });
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ MyGlobalService, importProvidersFrom(MyModule), ] });
@ManfredSteyer
@ManfredSteyer ng g @angular/core:standalone
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ […] ] });
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ importProvidersFrom(HttpClientModule), importProvidersFrom(RouterModule.forRoot(APP_ROUTES)), ] });
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ provideHttpClient(), provideRouter(APP_ROUTES), ] });
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ provideHttpClient( withInterceptors([authInterceptor]), ), provideRouter(APP_ROUTES, withPreloading(PreloadAllModules),
withDebugTracing(), ), ] });
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ provideLogger(loggerConfig), ] });
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ provideLogger(loggerConfig, withColor({ debug: 3 })
), ] });
@ManfredSteyer
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ provideLogger(loggerConfig, withColor({ debug: 3 })
), ] });
@ManfredSteyer export function provideLogger(config: LoggerConfig): Provider[] { […] }
@ManfredSteyer export function provideLogger(config: LoggerConfig): Provider[] { return [ LoggerService,
{ provide: LoggerConfig, useValue: config }, { provide: LogFormatter, useValue: config.formatter }, ]; }
@ManfredSteyer export function provideLogger(config: LoggerConfig): Provider[] { return [ LoggerService,
{ provide: LoggerConfig, useValue: config }, { provide: LogFormatter, useValue: config.formatter }, ]; }
@ManfredSteyer export function provideLogger(config: LoggerConfig): EnvironmentProviders { return makeEnvironmentProviders([ LoggerService,
{ provide: LoggerConfig, useValue: config }, { provide: LogFormatter, useValue: config.formatter }, ]); }
@ManfredSteyer export function provideLogger( config: LoggerConfig, ...featues: LoggerFeature[] ): EnvironmentProviders
{ return makeEnvironmentProviders([ LoggerService, […], features?.map(f => f.providers) ]); }
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer export const APP_ROUTES: Routes = [ […] { path:
'flight-booking', canActivate: [() => inject(AuthService).isAuthenticated()], component: FlightBookingComponent }, ]
@ManfredSteyer export const APP_ROUTES: Routes = [ […] { path:
'flight-booking', canActivate: [() => inject(AuthService).isAuthenticated()], component: FlightBookingComponent }, ]
@ManfredSteyer export const APP_ROUTES: Routes = [ […] { path:
'flight-booking', canActivate: [() => inject(AuthService).isAuthenticated()], resolve: { flights: () => inject(FlightService).findAll() }, component: FlightBookingComponent }, ]
@ManfredSteyer export const authInterceptor: HttpInterceptorFn = (req, next) => {
[…] }
@ManfredSteyer export const authInterceptor: HttpInterceptorFn = (req, next) => {
if (req.url.startsWith('https://[…]/')) { const headers = req.headers.set('Authorization', 'Bearer 12345'); req = req.clone({headers}); } […] }
@ManfredSteyer export const authInterceptor: HttpInterceptorFn = (req, next) => {
if (req.url.startsWith('https://[…]/')) { const headers = req.headers.set('Authorization', 'Bearer 12345'); req = req.clone({headers}); } return next(req); }
@ManfredSteyer export const authInterceptor: HttpInterceptorFn = (req, next) => {
if (req.url.startsWith('https://[…]/')) { const headers = req.headers.set('Authorization', 'Bearer 12345'); req = req.clone({headers}); } return next(req).pipe( tap(resp => console.log('response', resp)) ); }
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ provideHttpClient( withInterceptors([authInterceptor]), ), ] });
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ provideLogger({ level: LogLevel.DEBUG, appenders: [DefaultLogAppender],
formatter: (level, cat, msg) => [level, cat, msg].join(';'), }), ] });
@ManfredSteyer Free eBook (brand new) ANGULARarchitects.io/standalone-book Standalone Components Download here:
@ManfredSteyer
@ManfredSteyer Zone.js: Monkey Patching After Event Handler: Inform Angular CD
checks Components all components (default) or selected ones (OnPush)
@ManfredSteyer Zone.js: Magic Zone.js: ~100K Cannot patch async/await coarse grained
CD e.g. Components are always checked as a whole, even if only a tiny fraction changed
@ManfredSteyer Signals!
@ManfredSteyer Signals!
@ManfredSteyer Signal 4711 Consumer read set notify 4712
@ManfredSteyer flights: Flight[] = []; const flights = await this.flightService.findAsPromise(from,
to); this.flights = flights; <div *ngFor="let f of flights"> <flight-card [item]="f" /> </div>
@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 Signals are in an Early Stage! It will an
option; no need to update existing code!
@ManfredSteyer Fine-grained and Zone-less CD Convertible to Observables and vice
versa! No need to unsubscribe!
@ManfredSteyer Modern Angular: Lightweight Architectures Standalone Components and APIs Functional
Services Upcoming: Signals
@ManfredSteyer
@ManfredSteyer d Slides & Examples Remote Company Workshops and Consulting
http://angulararchitects.io