Decorators In Angular

Decorators In Angular

In this article, we will learn what is Angular Decorator and which decorators Angular supports. In our Angular App, we use Angular Decorators in a variety of areas. It's used to decorate components, directives, and Angular Modules, among other things.

Angular Decorators

An Angular Decorator is a function that allows you to add metadata to a class, method, accessor, property, or argument. The decorator is applied with the form @expression, where expression is the decorator's name.

Decorators are Typescript features that are not yet included in Javascript. The proposal stage is currently ongoing.

We need to add the experimentalDecorators to the tsconfig.json file to allow Angular Decorators. This is immediately added by the ng new command.

{
  "compilerOptions": {
    "target": "ES5",
    "experimentalDecorators": true
  }
}

Creating a new Decorator in Angular

The following code demonstrates how to make an Angular Decorator. The AppComponent class is decorated with the simpleDecorator. There are no counter-arguments.

import { Component, VERSION } from '@angular/core';
 
@simpleDecorator
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  name = 'Angular ' + VERSION.major;
 
  constructor() {
    console.log('Hello from Class constructor');
  }
 
  ngOnInit() {
    console.log((this as any).value1);
    console.log((this as any).value2);
  }
}
 
function simpleDecorator(target: any) {
  console.log('Hello from Decorator');
 
  Object.defineProperty(target.prototype, 'value1', {
    value: 100,
    writable: false
  });
 
  Object.defineProperty(target.prototype, 'value2', {
    value: 200,
    writable: false
  });
}
 
 
 
 
**** Console ***
 
Hello from Decorator
Hello from Class constructor
100
200

The decorator, as previously said, is a function. It receives the target as an argument, which is the AppComponent.

function simpleDecorator(target: any) {
  console.log('Hello from Decorator');

We add two new properties value1 and value2 to our AppComponent inside the function.

Object.defineProperty(target.prototype, 'value1', {
  value: 100,
  writable: false
});

Object.defineProperty(target.prototype, 'value2', {
  value: 200,
  writable: false
});

We can now use it to embellish our AppComponent.

@simpleDecorator
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

We may access the new properties from within the component.

ngOnInit() {
  console.log((this as any).value1);
  console.log((this as any).value2);
}

Decorator with Arguments

We need to develop a factory function that returns the Decorator function in order to generate a Decorator with arguments.

import { Component, VERSION } from '@angular/core';
 
@simpleDecorator({
  value1: '100',
  value2: '200'
})
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  name = 'Angular ' + VERSION.major;
 
  constructor() {
    console.log('Hello from Class constructor');
  }
 
  ngOnInit() {
    console.log((this as any).value1);
    console.log((this as any).value2);
  }
}
 
function simpleDecorator(args) {
  console.log(args);
 
  return function(target: any) {
    console.log('Hello from Decorator');
    console.log(typeof target);
    console.log(target);
 
    Object.defineProperty(target.prototype, 'value1', {
      value: args.value1,
      writable: false
    });
 
    Object.defineProperty(target.prototype, 'value2', {
      value: args.value2,
      writable: false
    });
  };
}

The decorator function is returned by the simpleDecorator, which takes the args as an argument. The rest of the code is identical to the previous section, with the exception that we use the args to populate the properties.

function simpleDecorator(args) {
  console.log(args);
 
  return function(target: any) {

On the component, we use the simpleDecorator as seen below:

@simpleDecorator({
  value1: '100',
  value2: '200'
})
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

List of All Angular Decorators

The following is a complete list of Angular Decorators.
  1. @NgModule
  2. @Component
  3. @Injectable
  4. @Directive
  5. @Pipe
  6. @Input
  7. @Output
  8. @Host
  9. @HostBinding
  10. @HostListener
  11. @ContentChild
  12. @ContentChildren
  13. @ViewChild
  14. @ViewChildren
  15. @Inject
  16. @Self
  17. @SkipSelf
  18. @Optional

We can categorize them into four main groups.
  1. Class decorators.
  2. Property decorators
  3. Method decorators
  4. Parameter decorators

Class decorators

Class decorators are used to decorating classes. In Angular, Class Decorators include @NgModule, @Component, @Injectable, @Directive, and @Pipe.

@NgModule

The @NgModule Decorator turns the class into an Angular Module and adds the necessary metadata.

@NgModule({
  providers?: Provider[],
  declarations?: Array<Type<any> | any[]>,
  imports?: Array<Type<any> | ModuleWithProviders<{}> | any[]>,
  exports?: Array<Type<any> | any[]>,
  bootstrap?: Array<Type<any> | any[]>,
  schemas?: Array<SchemaMetadata | any[]>,
  id?: string,
  jit?: true
})

@Component

Only when we use the @Component Decorator does Angular recognize the class as an Angular Component.

@Component({
  changeDetection?: ChangeDetectionStrategy,
  viewProviders?: Provider[],
  moduleId?: string,
 
  templateUrl?: string,
  template?: string,
  styleUrls?: string[],
  styles?: string[],
  animations?: any[],
  encapsulation?: ViewEncapsulation,
  interpolation?: [string, string],
  preserveWhitespaces?: boolean, 
})

@Injectable

The injectable decorator has two functions.

It tells Angular that this class requires a dependency. The metadata required to create the class's dependencies will be generated by the Angular compiler.

Second, we tell the Dependency Injection system how to supply the service using providedIn.

@Injectable({
  providedIn?: Type<any> | 'root' | 'platform' | 'any' | null
})

@Directive

A class is marked as an Angular directive with the @Directive Decorator. The directives let us change a DOM element's look, behavior, or layout.

@Directive({
  selector?: string,
  inputs?: string[],
  outputs?: string[],
  providers?: Provider[],
  exportAs?: string,
  queries?: { [key: string]: any;},
  host?: {[key: string]: string; },
  jit?: true
})

@Pipe

An Angular Pipe decorator that adds configuration details to a class.

@Pipe({
  name: string,
  pure?: boolean
})

Property Decorators

Property Decorators are applied to the class's properties.

@Input

The input decorator transforms a property into an input property. That is, it is capable of receiving data from the parent component. Property binding is used by the parent component to connect it to a component property. Angular updates the value in the child component whenever the value in the parent component changes.

Input(bindingPropertyName?: string)

@Output

The output property is decorated with the output property. We set it up as an EventEmitter. The data is passed as an argument to the event by the child component, which raises the event. The parent component uses event binding to listen for events and reads the data.

Output(bindingPropertyName?: string)

@ContentChild & @ContentChildren

The decorators ContentChild and ContentChildren are used to Query and obtain the reference to the Projected Content in the DOM. The content that this component receives from a parent component is known as projected content.

ContentChild(
  selector: string | Function | Type<any> | InjectionToken<unknown>, 
  opts?: {read?: any; static?: boolean;}
)

ContentChildren(
  selector: string | Function | Type<any> | InjectionToken<unknown>, 
  opts?: { descendants?: boolean;    read?: any;}
)

@ViewChild & @ViewChildren

To Query and retrieve the reference of the DOM element in the Component, use the ViewChild or ViewChildren decorators. ViewChild returns the first matched element, while ViewChildren produces a QueryList of all matching elements. These references can be used to manipulate the component's element properties.

ViewChild(
  selector: string | Function | Type<any> | InjectionToken<unknown>, 
  opts?: {
 read?: any; static?: boolean;}
)


ViewChildren(
  selector: string | Function | Type<any> | InjectionToken<unknown>, 
  opts?: {read?: any;}
)

@HostBinding

We can use the HostBinding to bind to a property of the host element. The host is an element to which our component or directive is attached. We can use this feature to change the host styles.

@HostBinding(hostPropertyName?: string)

Method decorators

The class's methods are decorated with method decorators.

@HostListener

The HostListener is an application that listens to host events. The host is an element to which our component or directive is attached. We may use HostListener to respond anytime the user interacts with the host element.

@HostListener(eventName: string, args?: string[])

Parameter decorators

The constructor argument of the class is decorated with parameter decorators.

@Inject

@Inject() is a constructor parameter decorator that instructs angular to inject the parameter with the dependency specified in the token. It's a time-consuming method of injecting the dependency.

Inject(token:any)

@Host

The @host parameter tells the DI framework to resolve the dependence in the view by checking injectors of child elements and stopping when it reaches the current component's host element.

@Self

The @Self decorator tells Angular to only look at the local injector for the dependency. The injector that is part of the present component or directive is known as the local injector.

@SkipSelf

The @SkipSelf decorator tells Angular to start searching for the dependency in the Parent Injector and work its way up.

@Optional

The dependency is marked as Optional with the @Optional annotation. If the dependency can't be discovered, it returns null rather than giving an exception.

You can also make your own personal decorations.

Conclusion

In this article, we learned what is Angular Decorator and which decorators Angular supports.

I hope this article helps you and you will like it.👍

If you have any doubt or confusion then free to ask in the comment section.

Post a Comment

Previous Post Next Post