Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

Reusable Components & Directives: Deep Dive

Reusable Components & Directives: Deep Dive

Manfred Steyer

October 27, 2022
Tweet

More Decks by Manfred Steyer

Other Decks in Programming

Transcript

  1. @ManfredSteyer Contents • Interacting with Content • Interacting with View

    • Working with Handles • Providers vs. ViewProviders
  2. @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>
  3. @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
  4. @ManfredSteyer Hooks 1) ngOnChanges 2) ngOnInit 3) ngDoCheck 4) ngAfterContentInit

    5) ngAfterContentChecked 6) ngAfterViewInit 7) ngAfterViewChecked 8) ngOnDestroy
  5. @ManfredSteyer Hooks 1) ngOnChanges 2) ngOnInit 3) ngDoCheck 4) ngAfterContentInit

    5) ngAfterContentChecked 6) ngAfterViewInit 7) ngAfterViewChecked 8) ngOnDestroy
  6. @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'); } }
  7. @ManfredSteyer Bindings @Directive({ selector: '[appClickWithWarning]' }) export class ClickWithWarningDirective implements

    OnInit { @Input() warning = 'Are you sure?'; @Output() appClickWithWarning = new EventEmitter(); }
  8. @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'; }
  9. @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 { … } }
  10. @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
  11. @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); } }
  12. @ManfredSteyer Implementation export class TooltipDirective implements OnInit { private viewRef:

    EmbeddedViewRef<unknown>; @Input('appTooltip') template: TemplateRef<unknown>; constructor( private host: ElementRef, private viewContainer: ViewContainerRef) { } ngOnInit(): void { this.viewRef = this.viewContainer.createEmbeddedView(this.template); […] } }
  13. @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
  14. @ManfredSteyer Structural Directive <div *ngFor="let f of flights; index as

    i"> <pre>{{i}}: {{ f | json }}</pre> </div> Template Micro Syntax
  15. @ManfredSteyer ngFor Implementation Structural Directive <div *ngFor="let f of flights;

    index as i"> <pre>{{i}}: {{ f | json }}</pre> </div> Template
  16. @ManfredSteyer $implicit ngForOf index Structural Directive <div *ngFor="let f of

    flights; index as i"> <pre>{{i}}: {{ f | json }}</pre> </div> Template context
  17. @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>
  18. @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>
  19. @ManfredSteyer Summary • Attribute Directive with Input, Output, HostBinding, HostListener

    • ElementRef, TemplateRef, ViewContrainerRef • *ngComponentOutlet, *ngTemplateOutlet • Struktruelle Direktive: Template + Micro Syntax