Decorators in Angular

Decorators in Angular

A decorator is a special kind of declaration in the TypeScript language. It can add additional functionality to a class method, property, or parameter. There are four main types of decorators:

  1. Class decorator
  2. Property decorator
  3. Method decorator.
  4. Parameter decorator.

Usage of decorators:

Decorators are an integral part of the Angular environment. Every Angular app uses a class decorator right from the start. Here are two examples of using class decorators:

In the Angular module:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';


import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
}
export class AppModule { }


and in Angular component:

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


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'demp-app';
}

We can see that both the Angular module and the Angular Component are simply standard Typescript classes. The only difference is in their decorators attached to them.

In the component decorator, we see that we define a selector (The Dom element name that we use in case we insert this component to a parent component.), a templateUrl (Which HTML file is attached to it) and styleUrls (Which CSS or SCSS file will attach to it).

In the module decorator, we can see which components and modules (if any) are attached to it. What is the default component (bootstrap) it be initiated, and so forth.

Property decorators are attached to the properties of an Angular class. they add additional functionality to the properties of an angular class. One common example of a property decorator is the @output decorator. the @output decorator enables the inner Angular components to trigger events on their parent components. This is how you define a property with an @output decorator:

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

@Component({
    selector: 'app-child',
    template: `<button class='btn btn-primary' (click)="valueChanged()">Click me</button> `
})
export class AppChildComponent {
    
    @Output() valueChange = new EventEmitter();
    
    Counter = 0;
    
    valueChanged() { // You can give any function name
        this.counter = this.counter + 1;
        this.valueChange.emit(this.counter);
    }
}

We see that there is a new property called: valueChange. Its type is EventEmitter. we trigger this new Event emitter by the function: this.valueChange.emit(this.counter) where this.counter is a property value which is transferred to the parent component.

Method decorators are attached to the methods of an Angular class. If you use an inner component inside a parent component. A good example of a method decorator is the @HostListener decorator which connects a JavaScript event such as key down event to a function inside a component.

@HostListener('keydown', ['$event']) 
confirmFirst(event: KeyboardEvent) { 
   if (!isNaN(Number(event.key))) { 
       return true; 
   } else { 
       return false; 
   }

}

An example of an implementation of a component can be:

<input type="text" id="txtIDNum" placeholder="ID number" maxlength="9" appInputNumbersOnly>

Where appInputNumbersOnly is the attribute directive of an Input HTML element. Every time the Input element is focused and there is a key down event, the method confirmFirst inside the directive is activated.

The @HostListener directive connects between the key down event and the confirmFirst function.

A parameter decorator is a decorator attached to a parameter in a Typescript class. one common example of a parameter class is an @Inject decorator. here is an example of that widget:

import { Component, Inject } from '@angular/core';
import { ChatWidget } from '../components/chat-widget';

@Component({
  selector: 'app-root',
  template: `Encryption: {{ encryption }}`
})
export class AppComponent {
  encryption = this.chatWidget.chatSocket.encryption;

  constructor(@Inject(ChatWidget) private chatWidget) { }
}

ChatWidget is an Angular service. By using the @Inject directive we ensure the chatWidget object is imported as a Singelton object. It is not an object that was instantiated in the class.

Creating a decorator:

A decorator is simply a typescript function. Here is a basic method decorator which write on the console at the beginning and the end of the class method:

export function log(): MethodDecorator {
  return (target: Function, key: string, descriptor: any) => {


    // key: name of the method
    // descriptor: the function itself


    const originalMethod = descriptor.value;


    descriptor.value =  function(...args: any[]) {


      // writes in the begining of the function
      console.log(`Entering ${key} method`);
      // execute the function itself
      const result = originalMethod.apply(this, args);
      // writes in the end of the function
      console.log(`Leaving ${key} method` );


      return result;
    };


    return descriptor;
  };
}

This method writes on the console when the function starts and when the function ends. basically, the decorator function returns a closure function which returns the descriptor itself.

We apply the decorator in the following way:

ngOnInit() {
  this.onMyload();
}


@log()
onMyload() {
  console.log('onMyload');
 
}

Since the onMyLoad function and the decorator (in our example) both write on the console, the output will be:

Entering onMyload method
onMyload
Leaving onMyload method

Conclusion

I hope you now have an idea about decorators in Angular and how to develop customized decorators for yourself.

I will be happy to receive any comments. Please send them to krasnoff.kobi@gmail.com

תודה רבה לך על השיתוף🙂 אני מזמינה אותך לקבוצה שלי: הקבוצה מחברת בין עסקים ויזמים במגוון תחומים. הקבוצה מייצרת שיתופי פעולה,אירועים משותפים ולקוחות: https://chat.whatsapp.com/BubG8iFDe2bHHWkNYiboeU

Like
Reply

To view or add a comment, sign in

More articles by Kobi Krasnoff

  • Promises vs. Observables

    Usages of both these objects Both of these objects are designed to handle asynchronous actions. Promises have been…

    1 Comment
  • Directives in Angular

    Directives are an important part of any Angular application. We use Built-in directives such as the RouterOutlet…

Explore content categories