Decorators are design patterns or functions that define how Angular features work. They make prior modifications to a class, service, or filter.
Angular supports four types of decorators:
A class decorator tells Angular if a particular class is a component or a module.
There are various class decorators in Angular, and among them, @Component
and @NgModule
are widely used.
import {Component} from '@angular/core';@Component({selector: 'app-root',templateUrl: '.app.component.html'})export class AppComponent {title = 'myapp';}
The code snippet above uses the @Component
decorator, shown in line 3.
Property decorators allow us to decorate some properties within our classes. We can quickly identify why we use any particular cproperty of a class like @Input()
, @Output()
, @Override()
, and so on. We can place the @Input()
decorator above the property with this decorator. The AngularJS compiler will create an input binding with the property name and link them.
function Override(label: string) {return function (target: any, key: string) {Object.defineProperty(target, key, {configurable: false,get: () => label});}}class Test {@ReadOnly('test') // invokes ReadOnly, which returns the decoratorname: string = 'pat';}let t = new Test();console.log(t.name); // 'test'
The decorated property is not writable in the code above and remains undefined. It’s important to note that the decorator cannot directly manipulate property values. Instead, an accessor is used.
Method decorators are used to decorate the method defined inside our class with functionality. A typical example of a method decorator is @HostListener
.
import { Component, HostListener } from '@angular/core';@Component({selector: 'example-component',template: 'A new component!'})export class ExampleComponent {@HostListener('click', ['$event'])onHostClick(event: Event) {// clicked, `event` available}}
The above code tells Angular that an event on our host has happened, and we want the decorated method to be called with the event.
The @HostListener
decorator is used before the onHostClick(
method.
Parameter decorators are applied to the constructor parameter of the class and are used when we need to tell Angular to inject a particular provider in a constructor.
@Inject()
is a widely used parameter decorator. We use this decorator to inject services in Angular classes.
import {Component, Inject } frin '@angular/core';import {ExampleService } from './my-service';@Component({selector: 'Test-component',template: 'Property decorator example'export class ParameterExample{constructor(@Inject(ExampleService) exampServ)console.log(exampServ);}})
In line 9, we use @Inject()
to inject our example service. We import this service in line 2 into our angular class named ParameterExample
.
We can find a working example containing a few concepts discussed here:
import { TestBed } from '@angular/core/testing'; import { AppComponent } from './app.component'; describe('AppComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [ AppComponent ], }).compileComponents(); }); it('should create the app', () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; expect(app).toBeTruthy(); }); it(`should have as title 'angular-test'`, () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; expect(app.title).toEqual('angular-test'); }); it('should render title', () => { const fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); const compiled = fixture.nativeElement as HTMLElement; expect(compiled.querySelector('.content span')?.textContent).toContain('angular-test app is running!'); }); });
isRed
property to be true
are red. Others are green.HostListener
method which, whenever we perform a click event, stops this particular event (alert
) from occurring in the template region. HostListener
method again, which calls the alert
method. This happens whenever we perform a click event in the region which doesn't exist inside the HTML template.