Author avatar

Parul Saxena

Defining Metadata with a Decorator in Angular

Parul Saxena

  • Aug 14, 2020
  • 6 Min read
  • 322 Views
  • Aug 14, 2020
  • 6 Min read
  • 322 Views
Languages Frameworks and Tools
Front End Web Developer
Client-side Frameworks
Angular

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:

  1. Class Decorators
  2. Property Decorators
  3. Method Decorators
  4. 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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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.

The expression for the property decorator will be called as a function at runtime, with the following two arguments:

  1. Either the constructor function of the class for a static member, or the prototype of the class for an instance member.
  2. 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.

1
2
3
4
5
6
7
8
9
10
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.

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:

  1. Either the constructor function of the class for a static member, or the prototype of the class for an instance member.
  1. The name of the member.
  1. 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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.

1
2
3
4
5
6
7
8
9
10
11
12
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
  }
}

The expression for the parameter decorator will be called as a function at runtime, with the following three arguments:

  1. Either the constructor function of the class for a static member, or the prototype of the class for an instance member.
  2. The name of the member.
  3. 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.

1