> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/angular/angular/llms.txt
> Use this file to discover all available pages before exploring further.

# @Directive

> Decorator that marks a class as an Angular directive

## 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

```typescript theme={null}
@Directive(metadata: Directive): TypeDecorator
```

## Parameters

<ParamField path="metadata" type="Directive" required>
  Configuration object that specifies how the directive should be processed and used.
</ParamField>

## Directive Metadata

### selector

<ParamField path="selector" type="string">
  CSS selector that identifies elements to which this directive is applied.

  ```typescript theme={null}
  selector: '[appHighlight]'    // Attribute selector
  selector: '.highlight'        // Class selector
  selector: 'button[type=submit]' // Combined selector
  ```
</ParamField>

### standalone

<ParamField path="standalone" type="boolean" default="true">
  When `true`, the directive does not need to be declared in an NgModule.

  ```typescript theme={null}
  standalone: true  // Recommended for new directives
  ```
</ParamField>

### inputs

<ParamField path="inputs" type="string[] | {name: string, alias?: string, required?: boolean, transform?: Function}[]">
  Input properties that accept data binding.

  ```typescript theme={null}
  inputs: ['color', {name: 'highlightColor', alias: 'highlight'}]
  ```
</ParamField>

### outputs

<ParamField path="outputs" type="string[]">
  Output properties that emit events.

  ```typescript theme={null}
  outputs: ['colorChanged']
  ```
</ParamField>

### providers

<ParamField path="providers" type="Provider[]">
  Services available for dependency injection in this directive.

  ```typescript theme={null}
  providers: [DirectiveService]
  ```
</ParamField>

### exportAs

<ParamField path="exportAs" type="string">
  Name for template variable references.

  ```typescript theme={null}
  exportAs: 'highlight'
  ```

  Usage: `<div appHighlight #h="highlight"></div>`
</ParamField>

### host

<ParamField path="host" type="{[key: string]: string}">
  Map of host element bindings, properties, attributes, and events.

  ```typescript theme={null}
  host: {
    '[style.backgroundColor]': 'backgroundColor',
    '(mouseenter)': 'onMouseEnter()',
    '(mouseleave)': 'onMouseLeave()',
    'role': 'button'
  }
  ```
</ParamField>

### hostDirectives

<ParamField path="hostDirectives" type="Type<unknown>[] | {directive: Type<unknown>, inputs?: string[], outputs?: string[]}[]">
  Directives to apply to the host element, enabling directive composition.

  ```typescript theme={null}
  hostDirectives: [
    TooltipDirective,
    {directive: DisabledDirective, inputs: ['appDisabled: disabled']}
  ]
  ```
</ParamField>

## Attribute Directive Example

```typescript highlight.directive.ts theme={null}
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:

```html theme={null}
<p appHighlight="yellow">Hover over me!</p>
<p [appHighlight]="color" defaultColor="lightblue">Custom colors</p>
```

## Structural Directive Example

```typescript unless.directive.ts theme={null}
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:

```html theme={null}
<p *appUnless="condition">Show this when condition is false</p>
```

## Host Bindings Example

```typescript button-role.directive.ts theme={null}
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

```typescript menu-item.directive.ts theme={null}
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:

```html theme={null}
<button appMenuItem tooltip="Save changes" [disabled]="!isValid">
  Save
</button>
```

## Input Transformation

```typescript auto-id.directive.ts theme={null}
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

```typescript parent.component.ts theme={null}
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

```typescript form-control.directive.ts theme={null}
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:

```html theme={null}
<input appFormControl #ctrl="formControl" [(ngModel)]="name">
<button (click)="ctrl.validate()">Validate</button>
<div *ngIf="!ctrl.valid && ctrl.touched">Field is required</div>
```

## Best Practices

<Warning>
  * 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`
</Warning>

<Tip>
  * 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
</Tip>

## Related APIs

* [@Component](/api/core/component) - Define components
* [@Input](/api/core/input-output#input) - Define input properties
* [@Output](/api/core/input-output#output) - Define output properties
* [ElementRef](/api/core/element-ref) - Access native DOM elements
* [TemplateRef](/api/core/template-ref) - Reference template for structural directives

## See Also

<CardGroup cols={2}>
  <Card title="Directives Guide" icon="book" href="/concepts/directives">
    Learn directive fundamentals
  </Card>

  <Card title="Attribute Directives" icon="book" href="/concepts/directives">
    Create attribute directives
  </Card>

  <Card title="Structural Directives" icon="book" href="/concepts/directives">
    Build structural directives
  </Card>

  <Card title="Directive Composition" icon="book" href="/concepts/directives">
    Compose directive behaviors
  </Card>
</CardGroup>
