Life Cycle of Angular Components

    Thursday, April 11, 202410 min read3916 views
    Life Cycle of Angular Components

    Table of Contents

    1. Introduction to Angular Components

    2. Working Function of Angular Components

    3. Specialty of Angular Components

    4. The Life Cycle of Angular Components

    5. Conclusion

    What are Angular Components?

    The angular components are the most basic UI building blocks of angular applications. They are the subsets of directives always associated with a template. These components can be easily created by Angular CLI.

    The command for the same is “ng generate c <component-name>”, where “c” stands for the component. The angular components can be declared as regular as well as stand-alone components. Regular components are always associated with its module, whereas stand-alone components are not associated with any module.

    At the time of component creation, unless we add “--flat” to the command that creates a component, angular will by default create all files required for that new component in a new folder whose name will be the same as of component.

    Every component has these 4 files initially. It contains 2 TS files, 1 HTML, and 1 CSS file. One file among those 2 ts files is for testing the component, while the other one contains the component class. Angular identifies it as a component class through its decorator @Component. Inside this class, we are supposed to write our logic and code.

    Inside the @Component decorator, “standAlone” is the field that makes a component standAlone when set to true or regular when set to false. But, in order to make a component regular, it is also necessary that the component’s class must be present in the declaration array of the required module.

    Working Function of Angular Components

    As discussed above, every component has 1 HTML file. We call it a template. It is a combination of normal html with angular data-binding syntax and angular expressions. On the browser, when we have to show our component then this template is shown on the user screen. The template is associated with its component through the @Component decorator, in which we should provide the “templateUrl” field with the path of our HTML file.

    Two Ways to Render a Component on a Browser

    A. Using our component as a child-component

    In this process, we use the string value of @Component’s field which is “selector”.
    Inside another template, we just have to use the component's selector field’s value as a custom html element.

    <!-- child.component.ts -->
    import { Component } from '@angular/core' ;
    @Component({ ..., selector : 'child-app'})
    
    <!-- parent-template.html -->
    
    <child-app></child-app>

    You can refer to the above code in order to understand the theory.

    B. With the help of routes

    In the routes array, we add an item in the form of an object whose basic fields are “path”, “component”, etc. Now, when the browser URL matches with the route's data, angular loads the corresponding component in the UI. It doesn't matter whether the component is standAlone or a regular one, angular loads it once the routes are matched. The route data should be given in the module’s class.

    The code snippet for the same is given below.

    <!-- app.component.ts -->
    import { Component } from '@angular/core' ;
    @Component({  ..., 
    	 template : "Hello World"
    	})
    export class AppComponent {}
    
    <!-- app.module.ts -->
    
    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { RouterModule, Routes } from '@angular/router';
    import { AppComponent } from './app.component';
    const routes : Routes = [  { path : 'app', component : AppComponent }];
    @NgModule({
      declarations: [AppComponent],  
      imports: [BrowserModule, RouterModule.forRoot(routes)], 
      bootstrap: [AppComponent],
    })
    export class AppModule {}

    Now, if the URL matches with the data of the first item of the routes array, then the AppComponent will be loaded and we will be able to see the message “Hello World” on the UI.

    3. Speciality of Angular Components

    Re-usability

    We can generate one component and use it at multiple places where we need it. 

    Data Binding

    Data binding is the process of connecting the app's user interface to the data that it shows. If the binding is configured correctly and the data sends the appropriate notifications, when the data's value changes, the elements bound to it automatically reflect the changes.

    Data binding can also imply that if the outer representation of data in an element changes, the underlying data will be instantly updated to reflect the change. For instance, whenever a user changes the value of a TextBox element, the underlying data value is automatically updated to reflect the change.

    This is the one feature available in Angular. By using data binding we can bind the component variable to the template(view). and whenever data changes change detection mechanism detects it and reflects the changes on view (template).

    There are two types of data binding

    1. One-way data binding

    In one way data binding binds the data from view to component or vice versa.

    If we want to bind the data from the template to the component then use event binding, and bind the data from the component to the template then use property binding or interpolation.

    Property Binding:

    <!-- app.component.html -->
    <h1 [ngStyle]="style">hello world</h1>
    <!-- app.component.ts -->
    export class ParentComponent {
      style = { 'background-color': 'red', 'font-size': '30px' };
    }
    image of Hello world

    Event Binding:

    <!-- app.component.html -->
    <input type="text" #fname ngModel (ngModelChange)="onChanges($event)"/>
    <!-- app.component.ts -->
    export class AppComponent {
      onChanges(event: any) {
        console.log(event);
      }
    }

    2. Two-way data binding

    In two-way data binding, we bind the data from both end template(view) to component and component to template(view). We use the ngModel directive for that

    <!-- text.component.ts --> 
    import { Component } from '@angular/core' ;
    @Component({  
    templateUrl : './template.html',
    })
    export class Text {
     text : string = "Hello Guys !" ;
    }
    <!--text.template.html -->
    <input [(ngModel)]="text"><h2>{{ text }}</h2>

    Dependency Injection

    It is a process in which we provide some part of a program (dependency) to other parts of the program that require them. In angular, Dependency Injection or DI provides the components with access to services and other resources. With the help of these mechanisms, we can make proper use of reusable code throughout the application.

    Below code snippet shows how angular performs Dependency Injection.

    <!-- auth.service.ts -->
    import { Injectable } from '@angular/core';
    @Injectable({
      providedIn: 'root',
    })
    export class AuthService {
      count = 0;
      getCount() {
        this.count++;
        return this.count;
      }
    }
    
    <!-- parent.component.ts -->
    import { AuthService } from '../auth.service';
    @Component({
      selector: 'app-parent',
      templateUrl: './parent.component.html',
      styleUrls: ['./parent.component.css'],
    })
    export class ParentComponent {
      count=0;
      constructor(private auth: AuthService) {
        this.count = auth.getCount();
        console.log('value of count is', this.count);
      }
    }
    

    Encapsulation

    Encapsulation means binding data into one specific unit. When we create any component using CLI  then it creates multiple files like HTML, CSS, ts, and spec files. All files are bundled together to build a component.

    Change Detection

    Change detection is a mechanism through which Angular synchronizes the state of the UI with the state of data. Change detection automatically updates the view or UI as soon as the component data model changes. This angular feature is handy as it reduces the work for developers to update the UI over time.

    4. Life cycle of Angular Components

    There are eight hook methods in the Angular component lifecycle. Right from the component initialization to the destruction of the same, we can intercept to any phase. As there are 8 hook methods, we have 8 lifecycle hook interfaces. Each interface defines the particular phase of the component. We need to implement these interfaces in order to access their corresponding hook method/s.

    Following sequence shows the lifecycle hook methods with their corresponding interface arranged in the order of their execution.

    1. ngOnChanges (from OnChanges interface)

    2. ngOnInit (from OnInit interface)

    3. ngDoCheck (from DoCheck interface)

    4. ngAfterContentInit (from AfterContentInit interface)

    5. ngAfterContentChecked (from AfterContentChecked interface)

    6. ngAfterViewInit (from AfterViewInit interface)

    7. ngAfterViewChecked (from AfterViewChecked interface)

    8. ngOnDestroy (from OnDestroy interface)

    1. ngOnChanges

    This method is called first among all other angular lifecycle hooks. This method is called when any data bound properties (decorated with @input decorator) changes in our component. If our component does not contain any input properties then this life cycle hook method is not called.

    This life cycle hook method contains an object of SimpleChanges classs as a parameter. This class is present in the angular core library. This object contains previous value, current value, and initial value property of our input variable. So, if we want to check the previous value of the input property then we can get it using SimpleChanges class Object.

    This life hook is also called when Angular's change detection algorithm detects pure changes on any input property. Pure changes are the changes in the primitive data type(number, boolean) variable. When non-primitive data types like object and array are changed this life cycle hook is not called but if the object reference and array are changed, then angular detects such changes and thus, this life cycle hook is called.

    <!--parent.component.html-->
    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'appParent',
      template: `
    	<input type="text" name="fname" #fname ngModel />
      	<button (click)="onChange(fname)">submit</button>
      	<appChild [FirstName]="firstName"></appChild>`,
    })
    export class ParentComponent {
      firstName = '';
      onChange(fname: any) {
        this.firstName = fname.value;
      }
    }
    <!--child.component.html-->
    import {Component, Input, OnChanges, OnInit, SimpleChanges} from'@angular/core';
    @Component({
      selector: 'appChild',
     template:`
    	<p>Firstname :{{ FirstName }}</p>`,
    })
    export class ChildComponent implements OnChanges {
      @Input() FirstName: any;
      constructor() {}
      ngOnChanges(changes: SimpleChanges): void {
        console.log(changes);
      }
    }
    

    When the FirstName input property of the child component changes this hook is called.

    2. ngOnInit

    This is the second lifecycle hook method and is executed after the ngOnChanges hook method. It is executed only once in the component's life cycle. This is the best place to do the HTTP calls which are required at the start of your application. All the input properties are available in this method.

    But if we try to access any element from the template using @ViewChild, @ViewChildren, we are not able to access it as they still need to be fully initialized.

    3. ngDoCheck

    This is the third lifecycle hook and is executed after the ngOnInit lifecycle hook. It is executed on every change detection cycle.

    This is the best place where all the changes are made in input properties like arrays and objects are available to us. We cannot detect these changes in the ngOnChanges hook. Custom change detection can be achieved through this hook method.

    4. ngAfterContentInit

    This is the fourth life cycle hook and is executed after the ngDoCheck hook method. Whenever there is any external component's content (content from the parent component) available and we want to project that content into our component's view, then after the completion of this content projection, this hook method is called.

    It is called only once in the component life cycle. It is called even if we don't project any external content in our component's view from the parent component. Below sample code shows the same.

    <!-- parent.component.html -->
    <app-child>
      <h1>content projected from parent to child</h1>
    </app-child>
    
    <!-- child.component.ts -->
    @Component({
      selector: 'app-child',
      template: '<ng-content></ng-content>,
      styleUrls: ['./child.component.css'],
    })
    export class ChildComponent {
    }

    From above code snippet, h1 tag is projected into our child component. In child component view, we can get that content projection using 'ng-content' tag.

    Angular initializes the the @ContentChild and @ContentChildren before this hook method, and so these properties are available to access in this hook method. @ContentChild is used to get the reference of the first matched projected content element and @ContentChildren is used to get all elements that match the same criteria.

    5. ngAfterContentChecked

    This is the fifth life cycle hook and is executed after the ngAfterContentInit hook method. It is executed after the completion of every change detection cycle, and after the external content is projected in our component. This hook method is called even if we don't project any external content in our component.

    6. ngAfterViewInit

    This is the sixth hook method and is executed after the ngAfterContentChecked hook method. Angular calls this method when our component's view and its child component's views are fully initialized.

    It is called only once in the life cycle of a component. Here, we can access the html elements from the template using @ViewChild and @ViewChildren decorators. In contrast, we are not able to access these elements in ngOnInit hook method.

    import { AfterViewInit,Component, OnInit,ViewChild,} from '@angular/core';
    @Component({
      selector: 'app-parent',
      template: `<h1 #h1Ele class="view">demo for @viewChild decorator</h1>`,
      styleUrls: ['./parent.component.css'],
    })
    export class ParentComponent implements AfterViewInit,OnInit {
      @ViewChild('h1Ele') h1ele!: ElementRef;
      ngOnInit(): void {
        console.log(this.h1ele);
      }
    
      ngAfterViewInit(): void {
        console.log(this.h1ele.nativeElement);
      }
    }
    

    In the above code snippet, the 'h1ele' element is not accessible in the ngOnInit lifecycle hook method, but it is accessible in the ngAfterViewInit lifecycle hook.

    7. ngAfterViewChecked

    This is the seventh life cycle hook and executes after the ngAfterViewInit hook. Angular calls this hook method after the execution of every change detection cycle.

    8. ngOnDestroy 

    This is the last hook method and angular calls it before angular destroys the components. In this method, we can perform the cleanup logic like unsubscribing the observable and detaching event handlers to avoid memory leaks.

    /* app.component.ts */
    import { Component, OnInit, OnDestroy } from '@angular/core' ;
    import { Subscription } from 'rxjs' ;
    
    @Component({...})
    export class FirstComponent implements OnInit, OnDestroy {
      sub!: Subscription;
      ngOnInit(): void {
         this.sub = interval(1000).subscribe((data: any) => {
         console.log(data);  
      }); 
      ngOnDestroy() : void {   
         this.sub.unsubscribe();
      }}

    Here, the code in this hook method is executed before angular destroys the component. This is the last hook method among the lifecycle methods. In other words, this lifecycle method is called before angular removes the component from the browser.

    Conclusion

    Angular components can be considered as on-demand User Interface structures. This is because, whenever an application requires an angular component, then angular loads that component. After the use of that particular component is finished, then angular automatically destroys that component. By doing so, the project runs smoothly.

    This mechanism of angular has made the applications more efficient to perform for any device regardless of their browser performance capacity. Angular also provides various component angular lifecycle hooks to perform operations on different phases of a component.

    24

    Related articles

    This website uses cookies to analyze website traffic and optimize your website experience. By continuing, you agree to our use of cookies as described in our Privacy Policy.