Ultimate Angular Decorators Cheat Sheet: A Complete Reference Guide

Introduction

Angular decorators are special functions that modify TypeScript classes, properties, methods, or parameters by adding metadata to enhance their functionality. They are prefixed with the @ symbol and are a fundamental part of Angular’s architecture. Decorators play a critical role in Angular development by enabling dependency injection, component definition, property binding, and many other core features without complex inheritance hierarchies.

Core Types of Angular Decorators

CategoryPurposeExamples
Class DecoratorsDefine Angular artifacts like components, modules, services@Component, @NgModule, @Injectable
Property DecoratorsWork with properties of classes@Input, @Output, @ViewChild
Method DecoratorsEnhance class methods@HostListener, @ContentChild
Parameter DecoratorsUsed for function arguments@Inject, @Optional, @Self

Class Decorators

@Component

Defines an Angular component.

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css'],
  providers: [ExampleService],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.Emulated
})
export class ExampleComponent { }

@NgModule

Defines an Angular module.

@NgModule({
  declarations: [ExampleComponent],
  imports: [CommonModule, FormsModule],
  exports: [ExampleComponent],
  providers: [ExampleService],
  bootstrap: [AppComponent]
})
export class ExampleModule { }

@Injectable

Marks a class as available for dependency injection.

@Injectable({
  providedIn: 'root' // Application-wide singleton
})
export class ExampleService { }

// Scoped to a specific module
@Injectable({
  providedIn: ExampleModule
})
export class ScopedService { }

@Directive

Creates a reusable directive.

@Directive({
  selector: '[appHighlight]',
  exportAs: 'appHighlight',
  host: { '(mouseenter)': 'onMouseEnter()' }
})
export class HighlightDirective { }

@Pipe

Defines a data transformation pipe.

@Pipe({
  name: 'formatDate',
  pure: true // Default is true (stateless)
})
export class FormatDatePipe implements PipeTransform {
  transform(value: any, ...args: any[]): any { }
}

Property Decorators

@Input

Defines an input property for a component.

@Input() itemData: any;
@Input('aliasName') itemData: any; // With alias

// With transform logic
@Input()
set itemData(value: any) {
  this._itemData = this.transformValue(value);
}
get itemData(): any {
  return this._itemData;
}

@Output

Defines an output event emitter.

@Output() itemSelected = new EventEmitter<any>();
@Output('selectAlias') itemSelected = new EventEmitter<any>(); // With alias

@ViewChild

Provides access to a child component, directive, or DOM element.

// Access component
@ViewChild(ChildComponent) childComp: ChildComponent;

// Access directive with static query (available in ngOnInit)
@ViewChild(ExampleDirective, { static: true }) directive: ExampleDirective;

// Access element reference
@ViewChild('inputRef') inputElement: ElementRef;

// With read option to get different token from the same element
@ViewChild('inputRef', { read: ViewContainerRef }) container: ViewContainerRef;

@ViewChildren

Similar to @ViewChild but returns all matching elements as a QueryList.

@ViewChildren(ChildComponent) childComps: QueryList<ChildComponent>;
@ViewChildren('itemRef') items: QueryList<ElementRef>;

@ContentChild & @ContentChildren

Access projected content.

@ContentChild(ChildComponent) projectedChild: ChildComponent;
@ContentChildren(ChildComponent) projectedChildren: QueryList<ChildComponent>;

@HostBinding

Binds a host element property to a component property.

@HostBinding('class.active') isActive = false;
@HostBinding('style.color') color = 'blue';
@HostBinding('attr.role') role = 'button';

Method Decorators

@HostListener

Listens for host element events.

@HostListener('click', ['$event'])
onClick(event: MouseEvent) {
  // Handle click event
}

@HostListener('window:resize', ['$event'])
onResize(event: UIEvent) {
  // Handle window resize
}

@ViewChild with methods

Accessing methods on child components.

@ViewChild('child') childComponent: ChildComponent;

callChildMethod() {
  this.childComponent.childMethod();
}

Parameter Decorators

@Inject

Manually specifies a dependency to inject.

constructor(@Inject(DOCUMENT) private document: Document) { }

@Optional

Makes a dependency optional.

constructor(@Optional() private logger: LoggerService) { }

@Self

Limits provider lookup to the current component’s injector.

constructor(@Self() private service: ExampleService) { }

@SkipSelf

Starts dependency lookup from the parent injector.

constructor(@SkipSelf() private parentService: ParentService) { }

@Host

Limits provider lookup to the host component.

constructor(@Host() private hostService: HostService) { }

@Attribute

Injects an attribute value from the host element.

constructor(@Attribute('role') public role: string) { }

Custom Decorators

You can create your own decorators for specialized use cases:

// Simple property decorator
function Capitalize() {
  return function(target: any, key: string) {
    let value = target[key];
    
    const getter = () => value;
    const setter = (next: string) => {
      value = next.charAt(0).toUpperCase() + next.slice(1);
    };
    
    Object.defineProperty(target, key, {
      get: getter,
      set: setter,
      enumerable: true,
      configurable: true
    });
  };
}

// Usage
export class ExampleComponent {
  @Capitalize() title: string = 'example'; // Will become 'Example'
}

Common Challenges and Solutions

ChallengeSolution
Circular dependenciesUse forwardRef(): constructor(@Inject(forwardRef(() => DependentService)) private service: DependentService)
Dynamic component loadingUse ComponentFactoryResolver with @ViewChild(ViewContainerRef)
Content projection issuesUse @ContentChild with ngAfterContentInit instead of ngOnInit
Change detection problemsUse ChangeDetectorRef.markForCheck() when using OnPush strategy
Property initialization timingUse *ngIf with the as syntax: *ngIf="item as selectedItem"

Best Practices

  1. Component Input/Output Naming: Use descriptive names that clearly indicate purpose.

  2. Metadata Consolidation: Group related decorators:

    @Component({...})
    export class DashboardComponent {
      // Group related inputs
      @Input() userData: User;
      @Input() userPreferences: Preferences;
      
      // Group related outputs
      @Output() save = new EventEmitter<User>();
      @Output() cancel = new EventEmitter<void>();
    }
    
  3. Directive Selectors: Use camelCase with brackets for attributes, kebab-case for elements:

    @Directive({ selector: '[appHighlight]' }) // Attribute directive
    @Component({ selector: 'app-user-card' })  // Element directive
    
  4. Query Timing:

    • Use {static: true} when you need access in ngOnInit
    • Use {static: false} (default) when targeting elements inside *ngIf or *ngFor
  5. Performance Considerations:

    • Limit the number of @HostListeners for frequently fired events
    • Use pure pipes rather than methods in templates
    • Implement OnPush change detection where appropriate

Advanced Decorator Patterns

Combining Decorators

@Component({...})
export class UserProfileComponent {
  @Input() @HostBinding('attr.user-id') userId: string;
  
  @HostListener('click')
  @LogMethod() // Custom decorator
  handleClick() { 
    // ... 
  }
}

Feature Flags with Decorators

function FeatureFlag(flagName: string) {
  return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = function(...args: any[]) {
      if (featureService.isEnabled(flagName)) {
        return originalMethod.apply(this, args);
      }
      console.warn(`Feature ${flagName} is disabled`);
      return null;
    };
    return descriptor;
  };
}

// Usage
@Component({...})
class ExampleComponent {
  @FeatureFlag('new-dashboard')
  showNewDashboard() {
    // Only runs if feature flag is enabled
  }
}

Resources for Further Learning

  • Official Documentation: Angular.io Decorators
  • GitHub Examples: Angular Decorators Samples
  • Books:
    • “Angular Development with TypeScript” by Yakov Fain and Anton Moiseev
    • “Pro Angular” by Adam Freeman
  • Courses:
    • Angular University’s “Angular Core Deep Dive”
    • Pluralsight’s “Angular Architecture and Best Practices”
  • Tools:
    • TypeScript Playground for testing custom decorators
    • Angular Schematics for generating decorated classes

Decorator Evolution in Angular Versions

VersionKey Changes
Angular 9Ivy compiler: more efficient decorator processing
Angular 10Stricter type checking for @Input() decorators
Angular 13Improved inheritance of decorators in derived classes
Angular 14Typed forms and improved decorator inference
Angular 15Directive composition API with hostDirectives
Angular 16Self-closing tags in component templates, improved signals
Angular 17New control flow syntax, deferrable views

This cheatsheet provides a comprehensive reference for Angular decorators, from basic usage to advanced patterns. As Angular continues to evolve, the decorator pattern remains central to its architecture, making this knowledge essential for effective Angular development.

Scroll to Top