Defining Metadata with a Decorator in Angular
Aug 14, 2020 • 6 Minute Read
Introduction
An Angular app is an interaction of the following Angular artifacts:
- Components
- Services
- Directives
- Pipes
- Modules
Each artifact is a TypeScript class. Angular recognizes the TypeScript class as an Angular artifact with the help of decorators. In this guide, you will learn about different decorators and their corresponding properties to understand how Angular identifies a simple TypeScript class as an Angular component, directive, pipe, service, or module.
What Angular Decorators Do
The whole purpose of Angular decorators is to store metadata about a class, method, or property. When you configure a component, you are providing a metadata for that class that tells Angular that you have a component, and that component has a specific configuration. Each decorator has a base configuration with some default values. When the decorator is created using the relevant factory, the default configuration is passed.
There are four types of decorators in Angular:
- Class Decorators
- Property Decorators
- Method Decorators
- Parameter Decorators
Class Decorators
Class Decorators are the top-level decorators that are used to define the purpose for the classes. They provide information to Angular that a particular class is a component, or module. For example:
import { NgModule, Component } from '@angular/core';
@Component({
selector: 'event-thumbnail',
template: `<div>Event Thumbnail Works!</div>`,
})
export class EventThumbnailComponent {
constructor() {
console.log('Hey I am a component!');
}
}
@NgModule({
imports: [],
declarations: [],
providers: []
})
export class AppModule {
constructor() {
console.log('Hey I am a module!');
}
}
Notice that both classes by themselves are effectively the same. No code is needed within the class to tell Angular that it is a component or a module.
Property Decorators
Property decorators are used to decorate the specific properties within the classes. Take a look at @Input(). Imagine that you have a property within the class that you want to have an input binding. Without decorators, you would have to define this property in your class for TypeScript to know about it, and then somewhere else tell Angular that you've got a property that you want to be an input.
From TypeScript's documentation:
The expression for the property decorator will be called as a function at runtime, with the following two arguments:
- Either the constructor function of the class for a static member, or the prototype of the class for an instance member.
- The name of the member.
With decorators, you can simply put the @Input() decorator above the property, for which Angular's compiler will automatically create an input binding from the property name and link them.
import { Component, Input } from '@angular/core';
@Component({
selector: 'event-thumbnail',
template: '<div>Event Thumbnail Works!</div>'
})
export class EventThumbnailComponent {
@Input()
exampleProperty: string;
}
Method Decorators
A Method Decorator decorates specific methods within your class with functionality. This is declared just before a method declaration.
From TypeScript's documentation:
The decorator is applied to the Property Descriptor for the method, and can be used to observe, modify, or replace a method definition. A method decorator cannot be used in a declaration file, on an overload, or in any other ambient context.
The expression for the method decorator will be called as a function at runtime, with the following three arguments:
- Either the constructor function of the class for a static member, or the prototype of the class for an instance member.
- The name of the member.
- The Property Descriptor for the member.
A good example of this is @HostListener. This tells Angular that when an event on your host happens, you want the decorated method to be called with the event.
import { Component, HostListener } from '@angular/core';
@Component({
selector: 'event-thumbnail',
template: '<div>Event Thumbnail Works!</div>'
})
export class EventThumbnailComponent {
@HostListener('click', ['$event'])
onHostClick(event: Event) {
// clicked, `event` available
}
}
Parameter Decorators
Parameter decorators are used to decorate parameters in your class constructors. For example- @Inject. It tells Angular that what you want that parameter to be initiated with.
import { Component, Inject } from '@angular/core';
import { MyService } from './my-service';
@Component({
selector: 'event-thumbnail',
template: '<div>Event Thumbnail Works!</div>'
})
export class EventThumbnailComponent {
constructor(@Inject(MyService) myService) {
console.log(myService); // MyService
}
}
From TypeScript's documentation:
The expression for the parameter decorator will be called as a function at runtime, with the following three arguments:
- Either the constructor function of the class for a static member, or the prototype of the class for an instance member.
- The name of the member.
- The ordinal index of the parameter in the function's parameter list. NOTE: A parameter decorator can only be used to observe that a parameter has been declared on a method.
Conclusion
Congratulations! You have learned about different types of decorators in Angular. You know the basic concept of designing the Angular Decorators. For more information, please refer to Decorators in TypeScript.
Learn More
Explore these Angular courses from Pluralsight to continue learning: