Tutorials Logic, IN info@tutorialslogic.com

Angular Decorators @Component, @Input, @Output

Decorator Foundations

Angular decorators attach framework metadata to classes and members. This reference groups decorators by responsibility so component metadata, dependency injection, host behavior, queries, and compatibility APIs form a readable system instead of a flat list.

Decorator Overview

Decorators are TypeScript features that Angular uses to attach metadata to classes, properties, methods, and constructor parameters. A decorator starts with @ and is placed immediately before the thing it describes. In Angular, decorators tell the framework what a class is, how it should be compiled, how it participates in dependency injection, and how it connects to templates.

For example, @Component() tells Angular that a class controls a UI view. @Injectable() tells Angular that a class can participate in dependency injection. @Input() allows a parent component to pass data into a child component. @HostListener() connects a class method to a DOM event on the host element.

  • Class decorators describe Angular building blocks such as components, directives, pipes, services, and modules.
  • Property decorators expose inputs, outputs, host bindings, and template queries.
  • Method decorators connect methods to host events.
  • Parameter decorators help Angular resolve special dependency injection cases.

Decorator Categories

Angular decorators become much easier to understand when you group them by the kind of code they decorate.

Category Decorators Main Purpose
Class decorators @Component, @Directive, @Pipe, @Injectable, @NgModule Tell Angular what role a class plays.
Property decorators @Input, @Output, @HostBinding, @ViewChild, @ViewChildren, @ContentChild, @ContentChildren Configure data flow, host bindings, and template queries.
Method decorators @HostListener Run a method when a host event happens.
Parameter decorators @Inject, @Optional, @Self, @SkipSelf, @Host Control dependency injection lookup behavior.

Metadata Processing

Angular does not use decorators as decoration only. The Angular compiler reads decorator metadata and uses it to generate efficient code for templates, dependency injection, change detection, queries, and component rendering. This is why a plain TypeScript class is not automatically an Angular component. Angular needs the metadata from @Component().

The class contains data and behavior. The decorator metadata tells Angular how to use that class in an application.

Decorator Metadata

Decorator Metadata
import { Component } from '@angular/core';

@Component({
  selector: 'app-message',
  standalone: true,
  template: `<p>{{ text }}</p>`
})
export class MessageComponent {
  text = 'Angular reads the @Component metadata';
}

Component and Directive Metadata

Component Metadata

@Component() is the most important Angular decorator. It declares a class as a component and provides metadata such as selector, template, styleUrl, imports, providers, and change detection settings. A component always has a template because it owns a section of the UI.

Use @Component() for reusable UI parts such as pages, cards, forms, dialogs, dashboards, layouts, navigation bars, and table rows.

@Component

@Component
import { ChangeDetectionStrategy, Component } from '@angular/core';

@Component({
  selector: 'app-profile-card',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <article class="profile-card">
      <h2>{{ name }}</h2>
      <p>{{ role }}</p>
    </article>
  `
})
export class ProfileCardComponent {
  name = 'Aarav';
  role = 'Frontend Developer';
}

Directive Metadata

@Directive() declares a class as a directive. A directive adds behavior to an existing element. Components are technically directives with templates, but a plain directive does not own its own template. Directives are perfect for reusable DOM behavior such as autofocus, permissions, validation styling, keyboard shortcuts, and hover effects.

Attribute Directive Definition

Attribute Directive Definition
import { AfterViewInit, Directive, ElementRef, inject } from '@angular/core';

@Directive({
  selector: '[appAutofocus]',
  standalone: true
})
export class AutofocusDirective implements AfterViewInit {
  private elementRef = inject(ElementRef<HTMLInputElement>);

  ngAfterViewInit() {
    this.elementRef.nativeElement.focus();
  }
}

Attribute Directive Usage

Attribute Directive Usage
<input appAutofocus placeholder="Search users" />

Pipe and Service Metadata

Pipe Metadata

@Pipe() declares a class as a pipe. Pipes transform values for display in templates. Angular includes built-in pipes such as date, currency, uppercase, and json. Custom pipes are useful for repeated display formatting.

Keep pipes focused on presentation. Heavy calculations, API calls, and state updates should usually live in services, computed signals, or component methods instead.

Custom Pipe Definition

Custom Pipe Definition
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'fileSize',
  standalone: true
})
export class FileSizePipe implements PipeTransform {
  transform(bytes: number): string {
    if (bytes < 1024) {
      return `${bytes} B`;
    }

    return `${(bytes / 1024).toFixed(1)} KB`;
  }
}

Custom Pipe Usage

Custom Pipe Usage
<p>Attachment size: {{ attachmentSize | fileSize }}</p>

Injectable Services

@Injectable() marks a class as available to Angular's dependency injection system. Services commonly use this decorator for API communication, shared state, authentication, logging, caching, and business logic. The most common configuration is providedIn: 'root', which registers a singleton service for the whole application.

Root Service Definition

Root Service Definition
import { Injectable, signal } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class UserService {
  private readonly _users = signal(['Asha', 'Rohan', 'Meera']);
  readonly users = this._users.asReadonly();

  addUser(name: string) {
    this._users.update(users => [...users, name]);
  }
}

Injected Service Usage

Injected Service Usage
import { Component, inject } from '@angular/core';
import { UserService } from './user.service';

@Component({
  selector: 'app-user-list',
  standalone: true,
  template: `
    @for (user of userService.users(); track user) {
      <p>{{ user }}</p>
    }
  `
})
export class UserListComponent {
  readonly userService = inject(UserService);
}

NgModule Metadata

@NgModule() defines a module that groups components, directives, pipes, providers, and imported modules. Modern Angular applications often use standalone components and route-level configuration instead of NgModules, but @NgModule() remains important because many existing Angular applications still use module-based architecture.

@NgModule

@NgModule
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AdminDashboardComponent } from './admin-dashboard.component';

@NgModule({
  declarations: [AdminDashboardComponent],
  imports: [CommonModule],
  exports: [AdminDashboardComponent]
})
export class AdminModule {}

Component Communication

Component Inputs

@Input() exposes a component or directive property so a parent template can bind to it. Inputs are how data flows into a child component. Modern Angular recommends the signal-based input() function for new projects, but decorator-based @Input() remains fully supported and is still common in existing codebases.

@Input() can also define aliases and transforms. Use aliases carefully because they create a different public template name from the internal class property name.

Decorator Input Definition

Decorator Input Definition
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-user-card',
  standalone: true,
  template: `
    <h3>{{ name }}</h3>
    <p>{{ role }}</p>
  `
})
export class UserCardComponent {
  @Input({ required: true }) name = '';
  @Input() role = 'Member';
}

Input Alias and Transform

Input Alias and Transform
<app-user-card
  [name]="currentUser.name"
  [role]="currentUser.role" />

Signal Input Definition

Signal Input Definition
import { Component, input } from '@angular/core';

@Component({
  selector: 'app-user-card',
  standalone: true,
  template: `<h3>{{ name() }}</h3>`
})
export class UserCardComponent {
  name = input.required<string>();
}

Component Inputs Alternative

Component Inputs Alternative
import { Component, Input, booleanAttribute } from '@angular/core';

@Component({
  selector: 'app-alert',
  standalone: true,
  template: `<p [class.important]="important">{{ message }}</p>`
})
export class AlertComponent {
  @Input({ alias: 'alertMessage' }) message = '';
  @Input({ transform: booleanAttribute }) important = false;
}

Component Outputs

@Output() exposes a custom event from a child component to its parent. It is commonly used for button clicks, row selection, form submission, closing modals, and notifying a parent that something changed. Modern Angular also supports the signal-friendly output() function.

Avoid output names that collide with native DOM events such as click, change, or input. Use names that describe the business event, such as saved, closed, selected, or submitted.

EventEmitter Output Definition

EventEmitter Output Definition
import { Component, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'app-confirm-button',
  standalone: true,
  template: `<button (click)="confirmed.emit()">Confirm</button>`
})
export class ConfirmButtonComponent {
  @Output() confirmed = new EventEmitter<void>();
}

Output Event Binding

Output Event Binding
<app-confirm-button (confirmed)="saveChanges()" />

Component Outputs Usage

Component Outputs Usage
import { Component, output } from '@angular/core';

@Component({
  selector: 'app-confirm-button',
  standalone: true,
  template: `<button (click)="confirmed.emit()">Confirm</button>`
})
export class ConfirmButtonComponent {
  confirmed = output<void>();
}

Host and Query Decorators

Host Properties

@HostBinding() binds a directive or component property to the host element. It can bind classes, styles, attributes, and DOM properties. This decorator is especially common in attribute directives.

Host Binding Definition

Host Binding Definition
import { Directive, HostBinding, Input } from '@angular/core';

@Directive({
  selector: '[appStatus]',
  standalone: true
})
export class StatusDirective {
  @Input() appStatus: 'success' | 'warning' | 'danger' = 'success';

  @HostBinding('class.is-success')
  get isSuccess() {
    return this.appStatus === 'success';
  }

  @HostBinding('attr.aria-live')
  ariaLive = 'polite';
}

Host Binding Usage

Host Binding Usage
<p [appStatus]="'warning'">Your password will expire soon.</p>

Host Events

@HostListener() listens for an event on the host element and calls a method when that event occurs. It can also listen to global targets such as window, document, and body. If the handler returns false, Angular prevents the default browser behavior for that event.

@HostListener

@HostListener
import { Directive, EventEmitter, HostListener, Output } from '@angular/core';

@Directive({
  selector: '[appEscapeClose]',
  standalone: true
})
export class EscapeCloseDirective {
  @Output() escapePressed = new EventEmitter<void>();

  @HostListener('document:keydown.escape', ['$event'])
  onEscape(event: KeyboardEvent) {
    event.stopPropagation();
    this.escapePressed.emit();
  }
}

View Queries

@ViewChild() and @ViewChildren() query elements, directives, or child components from the component's own template. Use @ViewChild() for the first matching item and @ViewChildren() for a list of matches.

Prefer normal template binding for most UI updates. Use view queries when you truly need access to a child component instance, directive instance, or DOM element API such as focus().

View Queries Example

View Queries Example
import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core';

@Component({
  selector: 'app-search-panel',
  standalone: true,
  template: `
    <input #searchInput placeholder="Search" />
    <button (click)="focusSearch()">Focus</button>
  `
})
export class SearchPanelComponent implements AfterViewInit {
  @ViewChild('searchInput') searchInput?: ElementRef<HTMLInputElement>;

  ngAfterViewInit() {
    console.log('Input is available after the view initializes');
  }

  focusSearch() {
    this.searchInput?.nativeElement.focus();
  }
}

@ViewChild() and @ViewChildren()

@ViewChild() and @ViewChildren()
import { Component, ElementRef, viewChild } from '@angular/core';

@Component({
  selector: 'app-search-panel',
  standalone: true,
  template: `<input #searchInput placeholder="Search" />`
})
export class SearchPanelComponent {
  searchInput = viewChild<ElementRef<HTMLInputElement>>('searchInput');

  focusSearch() {
    this.searchInput()?.nativeElement.focus();
  }
}

Content Queries

@ContentChild() and @ContentChildren() query content projected into a component with <ng-content>. They are useful when building reusable wrappers such as tabs, accordions, cards, form fields, and layout components.

Content Queries Example

Content Queries Example
import { AfterContentInit, Component, ContentChild, Directive } from '@angular/core';

@Directive({
  selector: '[appPanelTitle]',
  standalone: true
})
export class PanelTitleDirective {}

@Component({
  selector: 'app-panel',
  standalone: true,
  imports: [PanelTitleDirective],
  template: `
    <section class="panel">
      <ng-content />
    </section>
  `
})
export class PanelComponent implements AfterContentInit {
  @ContentChild(PanelTitleDirective) title?: PanelTitleDirective;

  ngAfterContentInit() {
    console.log('Projected title directive:', this.title);
  }
}

@ContentChild() and @ContentChildren()

@ContentChild() and @ContentChildren()
<app-panel>
  <h2 appPanelTitle>Account Settings</h2>
  <p>Projected panel body content</p>
</app-panel>

Dependency Injection Metadata

Parameter decorators change how Angular resolves dependencies in constructors. They are less common in new code that uses the inject() function, but they are still important in many Angular projects.

Decorator Meaning Common Use
@Inject() Use a specific injection token. Inject values that are not classes, such as config objects.
@Optional() Allow the dependency to be missing. Reusable components/directives with optional parent services.
@Self() Search only the current injector. Require a dependency from the local element/provider.
@SkipSelf() Start searching from the parent injector. Override or extend parent services.
@Host() Limit lookup at the host boundary. Directive/component relationships.

DI Parameter Decorators

DI Parameter Decorators
import { InjectionToken } from '@angular/core';

export interface AppConfig {
  apiUrl: string;
}

export const APP_CONFIG = new InjectionToken<AppConfig>('APP_CONFIG');

Parameter Decorators for Dependency Injection

Parameter Decorators for Dependency Injection
import { Inject, Injectable, Optional } from '@angular/core';
import { APP_CONFIG, AppConfig } from './tokens';

@Injectable()
export class ApiService {
  constructor(
    @Inject(APP_CONFIG) private config: AppConfig,
    @Optional() private logger?: Console
  ) {}

  get usersUrl() {
    return `${this.config.apiUrl}/users`;
  }
}

Choosing Decorator APIs

Decorator and Signal APIs

Modern Angular includes function-based APIs that reduce the need for some traditional property decorators in new code. These APIs are compiler-aware and usually integrate better with signals. The decorator APIs are still valid and widely used, so professional Angular developers should understand both styles.

Decorator API Modern Function API Use For
@Input() input(), input.required() Receiving values from a parent.
@Output() output() Emitting custom component events.
Two-way input plus output model() Creating two-way bindable component values.
@ViewChild(), @ViewChildren() viewChild(), viewChildren() Querying a component's own template.
@ContentChild(), @ContentChildren() contentChild(), contentChildren() Querying projected content.

Combined Decorator Example

In real applications, decorators are rarely isolated. A reusable component may use @Component(), @Input(), @Output(), and a service marked with @Injectable(). A directive may combine @Directive(), @Input(), @HostBinding(), and @HostListener().

Combined Decorators

Combined Decorators
import { Component, EventEmitter, Input, Output } from '@angular/core';

export interface Task {
  id: number;
  title: string;
  completed: boolean;
}

@Component({
  selector: 'app-task-card',
  standalone: true,
  template: `
    <article [class.done]="task.completed">
      <h3>{{ task.title }}</h3>
      <button (click)="toggle.emit(task.id)">
        {{ task.completed ? 'Reopen' : 'Complete' }}
      </button>
    </article>
  `
})
export class TaskCardComponent {
  @Input({ required: true }) task!: Task;
  @Output() toggle = new EventEmitter<number>();
}

Decorator Selection

Need Use
Create a UI block with its own template @Component()
Add reusable behavior to an existing element @Directive()
Format a value in a template @Pipe()
Create an injectable service @Injectable()
Receive data from a parent @Input() or input()
Emit an event to a parent @Output() or output()
Bind class, style, property, or attribute on the host @HostBinding()
Listen to a host or global event @HostListener()
Access a child element/component from your own template @ViewChild(), @ViewChildren(), or function query APIs
Access projected content @ContentChild(), @ContentChildren(), or function query APIs

Decorator Review

Angular decorators are the connection point between plain TypeScript classes and the Angular framework. They define components, directives, pipes, services, modules, data inputs, custom outputs, host behavior, template queries, content queries, and special dependency injection rules.

For beginners, the best path is to master @Component(), @Input(), @Output(), and @Injectable() first. Then learn directives with @HostBinding() and @HostListener(), followed by query decorators and dependency injection decorators. Once you understand what each decorator tells Angular, the framework becomes much easier to reason about.

Confirm the page outcome

Decorator Knowledge Check

4 checks
  • Decorators are TypeScript features that Angular uses to attach metadata to classes, properties, methods, and constructor parameters.
  • A decorator starts with @ and is placed immediately before the thing it describes.
  • In Angular, decorators tell the framework what a class is, how it should be compiled, how it participates in dependency injection, and how it connects to templates.
  • Angular does not use decorators as decoration only.

Decorator Design Questions

The query is not populated in the constructor because Angular has not created the view yet.

Usually not. click is already a browser event, so the template becomes ambiguous. Name the business event instead: confirmed, selected, saved, or closed.

@Injectable({ providedIn: 'root' }) both marks the class for Angular dependency injection and registers a tree-shakable root provider. The decorator matters most when the service itself asks Angular to inject constructor dependencies.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.