Custom Attribute Directives
Custom attribute directives let you create reusable element behaviors.
Attribute directives change the appearance or behavior of an element. Built-in examples include ngClass and ngStyle โ but you can create your own!
"Custom directive = apna rule banao โ jaise traffic police ka custom signal." Just like a traffic police officer creates custom signals for specific situations, you create custom directives for specific UI behaviors.
Use cases: highlight an element on hover, change color based on validation, add tooltip behavior, detect clicks outside an element.
Creating a directive is easy with Angular CLI:
ng g d directives/highlight
This generates:
import { Directive } from '@angular/core';\n\n@Directive({\n selector: '[appHighlight]',\n standalone: true\n})\nexport class HighlightDirective implements OnInit {\n // Your logic here\n}
Key points:
- @Directive decorator โ marks the class as a directive
- selector: '[appHighlight]' โ brackets mean it's an attribute selector
- standalone: true โ works without NgModule in Angular 18
ng g d= "generate directive" โ creates the file automatically
"ElementRef = element ka Aadhaar card โ se sab access kar sakte ho."
To access the DOM element inside a directive, inject ElementRef and optionally Renderer2:
constructor(private el: ElementRef, private renderer: Renderer2) {}\n\nngOnInit() {\n // Direct DOM access โ โ Avoid if possible (breaks SSR)\n this.el.nativeElement.style.backgroundColor = 'yellow';\n \n // Renderer2 โ โ
Safe for SSR\n this.renderer.setStyle(this.el.nativeElement, 'color', 'red');\n this.renderer.addClass(this.el.nativeElement, 'highlighted');\n this.renderer.setAttribute(this.el.nativeElement, 'data-id', '123');\n}
"ElementRef = direct touch, Renderer2 = gloves pehenke touch โ Renderer2 is safer for SSR."
Always prefer Renderer2 over direct ElementRef access โ it works in Service Workers and Server-Side Rendering (SSR).
Make your directive configurable with @Input:
@Input() appHighlight = 'yellow'; // Default color\n\nngOnInit() {\n this.renderer.setStyle(this.el.nativeElement, 'background-color', this.appHighlight);\n}
Usage in template:
<p appHighlight="red">This has red background</p>\n<p appHighlight>This has yellow (default) background</p>\n<p [appHighlight]="userColor">Dynamic color from component</p>
"Input dalo toh custom color, nahi dalo toh default โ flexible bhai."
Note how the @Input name appHighlight matches the directive selector. This is a common pattern โ the directive itself becomes a property binding.
Respond to user actions with @HostListener:
@HostListener('mouseenter') onMouseEnter() {\n this.renderer.setStyle(this.el.nativeElement, 'background-color', this.highlightColor);\n}\n\n@HostListener('mouseleave') onMouseLeave() {\n this.renderer.setStyle(this.el.nativeElement, 'background-color', null);\n}\n\n@HostListener('click', ['$event']) onClick(event: MouseEvent) {\n console.log('Clicked at:', event.clientX, event.clientY);\n}
"HostListener = CCTV camera โ element pe kya ho raha hai dekho."
Alternative: You can also use the host property in the @Directive decorator:
@Directive({\n selector: '[appHighlight]',\n host: {\n '(mouseenter)': 'onMouseEnter()',\n '(mouseleave)': 'onMouseLeave()'\n },\n standalone: true\n})Key Takeaways
- โ @Directive decorator creates custom attribute directives โ reusable element behaviors.
- โ ElementRef gives access to the DOM element; Renderer2 is safer for SSR.
- โ @Input() on the directive selector name makes it configurable.
- โ @HostListener responds to user events on the host element.
- โ Always use standalone: true in Angular 18 directives.
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login