We use cookies to enhance your experience on the site
CodeWorlds

Custom Directives

Directives are like secret ninja techniques - they extend the capabilities of elements.

Attribute Directive

1@Directive({
2  selector: '[appHighlight]',
3  standalone: true
4})
5export class HighlightDirective {
6  private el = inject(ElementRef);
7  private renderer = inject(Renderer2);
8
9  // Input with alias (directive name)
10  @Input() appHighlight = '#ffff00';
11  @Input() highlightOnFocus = false;
12
13  @HostListener('mouseenter')
14  onMouseEnter(): void {
15    this.setBackground(this.appHighlight);
16  }
17
18  @HostListener('mouseleave')
19  onMouseLeave(): void {
20    this.setBackground('');
21  }
22
23  @HostListener('focus')
24  onFocus(): void {
25    if (this.highlightOnFocus) {
26      this.setBackground(this.appHighlight);
27    }
28  }
29
30  private setBackground(color: string): void {
31    this.renderer.setStyle(this.el.nativeElement, 'backgroundColor', color);
32  }
33}
34
35// Usage
36<p appHighlight>Yellow highlight</p>
37<p [appHighlight]="'#c41e3a'">Red highlight</p>
38<input [appHighlight]="'#90EE90'" [highlightOnFocus]="true">

Structural Directive

1@Directive({
2  selector: '[appRepeat]',
3  standalone: true
4})
5export class RepeatDirective {
6  private templateRef = inject(TemplateRef<any>);
7  private viewContainer = inject(ViewContainerRef);
8
9  @Input() set appRepeat(count: number) {
10    this.viewContainer.clear();
11
12    for (let i = 0; i < count; i++) {
13      this.viewContainer.createEmbeddedView(this.templateRef, {
14        $implicit: i,  // Available as let-i
15        index: i,
16        first: i === 0,
17        last: i === count - 1
18      });
19    }
20  }
21}
22
23// Usage
24<div *appRepeat="5; let i; let isFirst = first">
25  Element {{ i }} {{ isFirst ? '(first)' : '' }}
26</div>

Permission Directive

1@Directive({
2  selector: '[appHasPermission]',
3  standalone: true
4})
5export class HasPermissionDirective {
6  private templateRef = inject(TemplateRef<any>);
7  private viewContainer = inject(ViewContainerRef);
8  private authService = inject(AuthService);
9
10  private hasView = false;
11
12  @Input() set appHasPermission(permission: string | string[]) {
13    const permissions = Array.isArray(permission) ? permission : [permission];
14    const hasPermission = this.authService.hasAnyPermission(permissions);
15
16    if (hasPermission && !this.hasView) {
17      this.viewContainer.createEmbeddedView(this.templateRef);
18      this.hasView = true;
19    } else if (!hasPermission && this.hasView) {
20      this.viewContainer.clear();
21      this.hasView = false;
22    }
23  }
24}
25
26// Usage
27<button *appHasPermission="'admin'">Admin Panel</button>
28<div *appHasPermission="['editor', 'admin']">Edit Content</div>
Go to CodeWorlds