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 Deep Dive: Components & Directives
Search
Manfred Steyer
PRO
March 21, 2023
Programming
0
410
Angular Deep Dive: Components & Directives
Manfred Steyer
PRO
March 21, 2023
Tweet
Share
More Decks by Manfred Steyer
See All by Manfred Steyer
The New NGRX Signal Store for Angular: 3+n Flavors of the Signal Store
manfredsteyer
PRO
0
23
Micro Frontends with Modern Angular and Island Architectures @ijs London 2024
manfredsteyer
PRO
0
80
Modern State Management in Angular: 3+n Flavors of the Signal Store @ijs London 2024
manfredsteyer
PRO
0
80
Changed Rules: Architectures with Lightweight Stores
manfredsteyer
PRO
0
240
Migrating to Signals: A Practical Workshop
manfredsteyer
PRO
0
410
Micro Frontends with Web Standards
manfredsteyer
PRO
1
300
The New NGRX Signal Store for Angular: 3+n Flavors
manfredsteyer
PRO
1
220
Leveraging the new NGRX Signal Store
manfredsteyer
PRO
0
170
Modern State Management in Angular: The 3+n Flavors of the NGRX Signal Store
manfredsteyer
PRO
0
110
Other Decks in Programming
See All in Programming
Hanami and htmx
bkuhlmann
0
210
ONE WEDGE_company_guide
1wedge_one
0
470
Snowflakeで眠ったデータを起こそう!
estie
0
120
検証も兼ねて個人開発でHonoとかと向き合った話
hanetsuki
0
870
try! Swift Tokyo 2024 参加報告 / try! Swift Tokyo 2024 Report
hironytic
0
200
dbtのドメイン分割による データ基盤の改善とDigdagとの連携
sakama
0
180
Behind VS Code Extensions for JavaScript / TypeScript Linnting and Formatting
unvalley
5
910
Git Rebase
bkuhlmann
11
1.6k
TYPO3 v13 – The road to LTS: What's new and new APIs
luisasofie_xoxo
0
200
⼤規模⾔語モデルの拡張(RAG)が 終わったかも知れない件について
nearme_tech
23
15k
今、知っておきたい! 生成AIエージェントの世界
elith
3
350
PHPの次期バージョンはこの時期どうなっているのか - Internalsの開発体制について - PHPカンファレンス小田原
youkidearitai
PRO
1
190
Featured
See All Featured
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
221
21k
Learning to Love Humans: Emotional Interface Design
aarron
267
39k
The World Runs on Bad Software
bkeepers
PRO
61
6.7k
The Brand Is Dead. Long Live the Brand.
mthomps
49
28k
Robots, Beer and Maslow
schacon
PRO
155
7.9k
Side Projects
sachag
451
41k
For a Future-Friendly Web
brad_frost
172
9k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
155
14k
Adopting Sorbet at Scale
ufuk
68
8.6k
Teambox: Starting and Learning
jrom
128
8.4k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
30
6k
How to Ace a Technical Interview
jacobian
272
22k
Transcript
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer Goal • Learn advanced concepts • Try them out
@ManfredSteyer Manfred Steyer
@ManfredSteyer Contents • Interacting with Content • Interacting with View
• Working with Handles • Providers vs. ViewProviders
@ManfredSteyer Why is this Intersting? • Reusable Components (Component Libraries)
• Better Understanding for Angular
@ManfredSteyer
@ManfredSteyer Case Study #1: Tabbed Pane
@ManfredSteyer Tabbed Pane <app-tabbed-pane> <app-tab title="Upcoming Flights"> <p>No upcoming flights!</p>
</app-tab> <app-tab title="Operated Flights"> <p>No operated flights!</p> </app-tab> <app-tab title="Cancelled Flights"> <p>No cancelled flights!</p> </app-tab> </app-tabbed-pane>
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer View vs. Content @Component({ selector: 'tab', template: ` <div
*ngIf="visible"> <h1>{{title}}</h1> <div> <ng-content></ng-content> </div> </div> ` }) export class TabComponent { @Input() title: string; visible: boolean = true; } Content <tab title="Booked"> Sample Text ... </tab> View
@ManfredSteyer Hooks 1) ngOnChanges 2) ngOnInit 3) ngDoCheck 4) ngAfterContentInit
5) ngAfterContentChecked 6) ngAfterViewInit 7) ngAfterViewChecked 8) ngOnDestroy
@ManfredSteyer Hooks 1) ngOnChanges 2) ngOnInit 3) ngDoCheck 4) ngAfterContentInit
5) ngAfterContentChecked 6) ngAfterViewInit 7) ngAfterViewChecked 8) ngOnDestroy
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer Handles <app-tabbed-pane #pane> […] </app-tabbed-pane> Current Page: {{ pane.currentPage
}}
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer Providers @Component({ […], providers: [NavigatorService] }) export class TabbedPaneComponent
{ […] }
@ManfredSteyer Providers @Component({ […], providers: [NavigatorService] // Visible in View
and Content }) export class TabbedPaneComponent { […] }
@ManfredSteyer View Providers @Component({ […], viewProviders: [NavigatorService] // Visible only
in View }) export class TabbedPaneComponent { […] }
@ManfredSteyer
@ManfredSteyer Summary • Content vs. View • [Content|View][Child|Children] • Providers
vs. ViewProviders • Handles
@ManfredSteyer Directives • „Components without Templates“ • Add behavior to
an element • Examples: ngModel, ngClass, ngStyle
@ManfredSteyer
@ManfredSteyer Case Study <button appClickWithWarning>Delete</button>
@ManfredSteyer Simple Example @Directive({ […], selector: '[appClickWithWarning]' }) export class
ClickWithWarningDirective implements OnInit { constructor(private elementRef: ElementRef) { } ngOnInit(): void { this.elementRef .nativeElement.setAttribute('class', 'btn btn-danger'); } }
@ManfredSteyer Calling a Directive <button appClickWithWarning>Delete</button> Host-Element
@ManfredSteyer Bindings @Directive({ […], selector: '[appClickWithWarning]' }) export class ClickWithWarningDirective
implements OnInit { @Input() warning = 'Are you sure?'; @Output() appClickWithWarning = new EventEmitter(); }
@ManfredSteyer Bindings @Directive({ […], selector: '[appClickWithWarning]' }) export class ClickWithWarningDirective
implements OnInit { @Input() warning = 'Are you sure?'; @Output() appClickWithWarning = new EventEmitter(); @HostBinding('class') classBinding = 'btn btn-danger'; }
@ManfredSteyer Bindings @Directive({ […], selector: '[appClickWithWarning]' }) export class ClickWithWarningDirective
implements OnInit { @Input() warning = 'Are you sure?'; @Output() appClickWithWarning = new EventEmitter(); @HostBinding('class') classBinding = 'btn btn-danger'; @HostListener('click', ['$event']) handleClick($event: MouseEvent): void { … } }
@ManfredSteyer Calling the Directive <button (appClickWithWarning)="delete()" message="Sure?">Delete</button>
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer Example: Tooltip <input [appTooltip]="tmpl"> <ng-template #tmpl> <h3>2 Tips for
Success</h3> <ol> <li>Don't tell everything!</li> </ol> </ng-template> ViewContainer
@ManfredSteyer Implementation @Directive({ […], selector: '[appTooltip]' }) export class TooltipDirective
implements OnInit { @Input('appTooltip') template: TemplateRef<unknown>; constructor(private host: ElementRef, private viewContainer: ViewContainerRef) { } ngOnInit(): void { this.viewContainer.createEmbeddedView(this.template); } }
@ManfredSteyer Implementation export class TooltipDirective implements OnInit { private viewRef:
EmbeddedViewRef<unknown>; @Input('appTooltip') template: TemplateRef<unknown>; constructor( private viewContainer: ViewContainerRef) { } ngOnInit(): void { this.viewRef = this.viewContainer.createEmbeddedView(this.template); […] } }
@ManfredSteyer Mouse-Events const elm = this.host.nativeElement as HTMLElement; elm.addEventListener('mouseover', ()
=> { […] }); elm.addEventListener('mouseout', () => { […] });
@ManfredSteyer Iterate over Projected Root Nodes this.viewRef.rootNodes.forEach(nativeElement => { nativeElement.hidden
= true; }); <input [appTooltip]="tmpl"> <ng-template #tmpl> <h3>2 Tips for Success</h3> <ol> <li>Don't tell everything!</li> </ol> </ng-template> Root Nodes
@ManfredSteyer
@ManfredSteyer Passing Parameters to Templates this.viewContainer.createEmbeddedView(this.template, { $implicit: 'Tooltip!', helpLink:
'http://www.google.com' }); Context
@ManfredSteyer Using Parameters in Template <ng-template #tmpl let-title let-link="helpLink"> <h3>{{title}}</h3>
<p> Deletes EVERYTHING! </p> <a [href]="link">More</a> </ng-template>
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer ViewContainer • createEmbeddedView • createComponent
@ManfredSteyer ContentChildren • @ContentChildren(MyComponentOrDirective, { read: ElementRef | ViewContainerRef })
• Same for @ContentChild, @ViewChildren, @ViewChild
@ManfredSteyer
@ManfredSteyer Structural Directive <div *ngFor="let f of flights; index as
i"> <pre>{{i}}: {{ f | json }}</pre> </div> Template Micro Syntax
@ManfredSteyer ngFor Implementation Structural Directive <div *ngFor="let f of flights;
index as i"> <pre>{{i}}: {{ f | json }}</pre> </div> Template
@ManfredSteyer $implicit ngForOf index Structural Directive <div *ngFor="let f of
flights; index as i"> <pre>{{i}}: {{ f | json }}</pre> </div> Template context
@ManfredSteyer Syntax Sugar <div *ngFor="let f of flights; index as
i"> <pre>{{i}}: {{ f | json }}</pre> </div> <ng-template ngFor let-f [ngForOf]="flights" let-i="index"> <div> <pre>{{i}}: {{ f | json }}</pre> </div> </ng-template>
@ManfredSteyer Case Study #2: DataTable
@ManfredSteyer DataTable <app-data-table [data]="flights"> <div *appTableField="let data as 'id'">{{data}}</div> <div
*appTableField="let data as 'from'">{{data}}</div> <div *appTableField="let data as 'to'">{{data}}</div> <div *appTableField="let data as 'date'"> {{data | date:'dd.MM.yyyy HH:mm'}} </div> </app-data-table>
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer 2 1 3 4
@ManfredSteyer Case Study #3: Formatting/Parsing Dates <input [(ngModel)]="date" appDate name="date">
@ManfredSteyer
@ManfredSteyer Summary ContentChildren & ViewChildren Handles ViewProviders Attribute Directives Templates
& ViewContainer Structural Directives Control Value Accessor