Overview
The @Directive decorator marks a class as an Angular directive and provides configuration metadata. Directives attach custom behavior to elements in the DOM.
Signature
@ Directive ( metadata : Directive ): TypeDecorator
Parameters
Configuration object that specifies how the directive should be processed and used.
selector
CSS selector that identifies elements to which this directive is applied. selector : '[appHighlight]' // Attribute selector
selector : '.highlight' // Class selector
selector : 'button[type=submit]' // Combined selector
standalone
When true, the directive does not need to be declared in an NgModule. standalone : true // Recommended for new directives
inputs
string[] | {name: string, alias?: string, required?: boolean, transform?: Function}[]
Input properties that accept data binding. inputs : [ 'color' , { name: 'highlightColor' , alias: 'highlight' }]
outputs
Output properties that emit events. outputs : [ 'colorChanged' ]
providers
Services available for dependency injection in this directive. providers : [ DirectiveService ]
exportAs
Name for template variable references. Usage: <div appHighlight #h="highlight"></div>
host
Map of host element bindings, properties, attributes, and events. host : {
'[style.backgroundColor]' : 'backgroundColor' ,
'(mouseenter)' : 'onMouseEnter()' ,
'(mouseleave)' : 'onMouseLeave()' ,
'role' : 'button'
}
hostDirectives
hostDirectives
Type<unknown>[] | {directive: Type<unknown>, inputs?: string[], outputs?: string[]}[]
Directives to apply to the host element, enabling directive composition. hostDirectives : [
TooltipDirective ,
{ directive: DisabledDirective , inputs: [ 'appDisabled: disabled' ]}
]
Attribute Directive Example
import { Directive , ElementRef , Input , HostListener } from '@angular/core' ;
@ Directive ({
selector: '[appHighlight]' ,
standalone: true
})
export class HighlightDirective {
@ Input () appHighlight = 'yellow' ;
@ Input () defaultColor = 'transparent' ;
constructor ( private el : ElementRef ) {}
@ HostListener ( 'mouseenter' ) onMouseEnter () {
this . highlight ( this . appHighlight );
}
@ HostListener ( 'mouseleave' ) onMouseLeave () {
this . highlight ( this . defaultColor );
}
private highlight ( color : string ) {
this . el . nativeElement . style . backgroundColor = color ;
}
}
Usage:
< p appHighlight = "yellow" > Hover over me! </ p >
< p [appHighlight] = "color" defaultColor = "lightblue" > Custom colors </ p >
Structural Directive Example
import { Directive , Input , TemplateRef , ViewContainerRef } from '@angular/core' ;
@ Directive ({
selector: '[appUnless]' ,
standalone: true
})
export class UnlessDirective {
private hasView = false ;
constructor (
private templateRef : TemplateRef < any >,
private viewContainer : ViewContainerRef
) {}
@ Input () set appUnless ( condition : boolean ) {
if ( ! condition && ! this . hasView ) {
this . viewContainer . createEmbeddedView ( this . templateRef );
this . hasView = true ;
} else if ( condition && this . hasView ) {
this . viewContainer . clear ();
this . hasView = false ;
}
}
}
Usage:
< p *appUnless = "condition" > Show this when condition is false </ p >
Host Bindings Example
import { Directive , HostBinding , HostListener , Input } from '@angular/core' ;
@ Directive ({
selector: '[appButtonRole]' ,
standalone: true ,
host: {
'role' : 'button' ,
'[attr.aria-pressed]' : 'pressed' ,
'[class.pressed]' : 'pressed'
}
})
export class ButtonRoleDirective {
@ Input () pressed = false ;
@ HostListener ( 'click' )
toggle () {
this . pressed = ! this . pressed ;
}
}
Directive Composition
import { Directive } from '@angular/core' ;
import { TooltipDirective } from './tooltip.directive' ;
import { DisabledDirective } from './disabled.directive' ;
@ Directive ({
selector: '[appMenuItem]' ,
standalone: true ,
hostDirectives: [
{
directive: TooltipDirective ,
inputs: [ 'tooltipText: tooltip' ]
},
{
directive: DisabledDirective ,
inputs: [ 'isDisabled: disabled' ]
}
]
})
export class MenuItemDirective {
// Inherits tooltip and disabled functionality
}
Usage:
< button appMenuItem tooltip = "Save changes" [disabled] = "!isValid" >
Save
</ button >
import { Directive , Input } from '@angular/core' ;
@ Directive ({
selector: '[appAutoId]' ,
standalone: true ,
host: {
'[id]' : 'id'
}
})
export class AutoIdDirective {
private static nextId = 0 ;
@ Input ({ transform : ( value : string | number ) =>
value ? String ( value ) : `auto-id- ${ AutoIdDirective . nextId ++ } `
})
id : string = '' ;
}
Querying Directive Instances
import { Component , ViewChildren , QueryList , AfterViewInit } from '@angular/core' ;
import { HighlightDirective } from './highlight.directive' ;
@ Component ({
selector: 'app-parent' ,
standalone: true ,
imports: [ HighlightDirective ],
template: `
<p appHighlight="red">First</p>
<p appHighlight="blue">Second</p>
<p appHighlight="green">Third</p>
`
})
export class ParentComponent implements AfterViewInit {
@ ViewChildren ( HighlightDirective ) highlights !: QueryList < HighlightDirective >;
ngAfterViewInit () {
console . log ( `Found ${ this . highlights . length } highlight directives` );
}
}
Export As Example
form-control.directive.ts
import { Directive , Input } from '@angular/core' ;
@ Directive ({
selector: '[appFormControl]' ,
standalone: true ,
exportAs: 'formControl'
})
export class FormControlDirective {
@ Input () value : any ;
valid = true ;
touched = false ;
markAsTouched () {
this . touched = true ;
}
validate () {
this . valid = !! this . value ;
return this . valid ;
}
}
Usage:
< input appFormControl #ctrl = "formControl" [(ngModel)] = "name" >
< button (click) = "ctrl.validate()" > Validate </ button >
< div *ngIf = "!ctrl.valid && ctrl.touched" > Field is required </ div >
Best Practices
Keep directives focused on a single responsibility
Use descriptive selector names with prefixes (e.g., appHighlight)
Prefer host metadata over @HostBinding and @HostListener decorators
Clean up subscriptions in ngOnDestroy
Use structural directives to conditionally add/remove DOM elements
Use attribute directives to change appearance or behavior
Leverage directive composition with hostDirectives to reuse functionality
See Also
Directives Guide Learn directive fundamentals
Attribute Directives Create attribute directives
Structural Directives Build structural directives
Directive Composition Compose directive behaviors