Attribute directives change the appearance or behavior of an existing element without adding or removing anything from the DOM. This lesson covers the built-in options and how to write your own.
What Is an Attribute Directive?
An attribute directive listens to an element's properties and events and modifies that same element in response, changing a style, a class, or an ARIA attribute, without creating or destroying any DOM nodes.
Angular ships two commonly used built-in attribute directives, ngClass and ngStyle, and lets you write custom ones with the @Directive decorator for any reusable DOM behavior.
ngClass accepts a string, an array of class names, or an object mapping class names to booleans.
ngStyle accepts an object mapping CSS property names to values.
For a single conditional class or style, [class.name]/[style.prop] are simpler than ngClass/ngStyle.
Custom attribute directives use @Directive({ selector: '[appName]' }).
Attribute Directives Cheatsheet
Built-in directives plus the anatomy of a custom one.
Directive/API
Example
Purpose
ngClass (object)
[ngClass]="{active: isActive}"
Toggle multiple classes conditionally
ngStyle
[ngStyle]="{color: c}"
Set multiple inline styles
[class.x]
[class.active]="isActive"
Toggle a single class
@Directive
@Directive({ selector: '[appFoo]' })
Define a custom directive
@Input()
@Input() color = 'yellow';
Configure the directive from the template
@HostListener
@HostListener('click')
React to events on the host element
@HostBinding
@HostBinding('class.active')
Bind a property/class on the host element
A Custom Directive With an Input
Custom attribute directives can accept configuration through @Input() (or the newer input() function), just like components, making them reusable across different contexts.
Naming the input the same as the selector (appHighlight) lets you configure it inline: <p appHighlight="lightblue">.
@HostBinding vs Direct DOM Manipulation
@HostBinding lets you bind a class, style, or property on the host element declaratively, which Angular's change detection manages for you, generally preferable to manually mutating ElementRef.nativeElement, especially for server-side rendering compatibility.
import { Directive, HostBinding, Input } from '@angular/core';
@Directive({
selector: '[appActiveClass]',
standalone: true,
})
export class ActiveClassDirective {
@Input() appActiveClass = false;
@HostBinding('class.active')
get isActive() {
return this.appActiveClass;
}
}
ngClass/ngStyle vs Single Bindings
For a single conditional class or style, [class.name]/[style.prop] bindings are simpler and slightly cheaper than ngClass/ngStyle. Reach for ngClass/ngStyle when you need to toggle several classes or styles together from one expression.
Common Mistakes
Reaching for ngClass with a single class when [class.name] would be simpler and clearer.
Manipulating ElementRef.nativeElement.style directly instead of using @HostBinding, which breaks in server-side rendering contexts.
Forgetting @Input() on a directive's configuration property, leaving it permanently at its default value.
Not cleaning up manually added event listeners in directives that don't use @HostListener.
Key Takeaways
Attribute directives change an existing element's appearance or behavior without altering DOM structure.
ngClass and ngStyle are built-in attribute directives for toggling multiple classes or styles at once.
Custom directives use @Directive, @Input(), @HostListener, and @HostBinding to build reusable behavior.
Prefer @HostBinding over direct DOM manipulation for better testability and SSR compatibility.
Pro Tip
Name a custom directive's primary @Input() the same as its selector (like appHighlight) so consumers can configure it inline on the same attribute, matching the ergonomics of Angular's own built-in directives.
You now understand attribute directives and how to build your own. Next, learn about Angular Pipes for transforming data directly in templates.