Learn Angular in 10 days – Day 4 – Part 1

Lab 11 – Download Source Code

Finally completed Day 3.  🙂C8

I have seen people getting scared because of long and big articles hence I have decided to write multiple small article for each day instead of writing one big article. In each article we will cover 1 or 2 or max 3 labs.

In this lab we will explore Angular Services.

Note: Before you proceed make sure that your TypeScript compiler is executing in watch mode, and your web server is running. If you are forgot how to do it, go with day 2 again.

Complete Series

  1. Day 1 – Part 1
  2. Day 1 – Part 2
  3. Day 2
  4. Day 3
  5. Day 4 – Part 1
  6. Day 4 – Execution trick
  7. Day 4 – Part 2
  8. Day 4 – Part 3
  9. Day 5 (Coming soon)
  10. Day 6 (Coming soon)
  11. Day 7 (Coming soon)
  12. Day 8 (Coming soon)
  13. Day 9 (Coming soon)
  14. Day 10 (Coming soon)

Introduction to Angular Services

In Angular, Services represents the injectable application logic.

  • Technically it will be a simple class encapsulating some king of logic. It can be any logic. It can be “a logic to make server call, a logic to create text file, logic to log messages”.
  • Injectable means – instances of those classes will not be created manually. Rather at run time it will be created by Angular framework and make it available to other Application. This is called “Dependency Injection”.

Dependency injection or DI is not an Angular concept. It’s a design pattern. It says “Application will not create the Dependency instance. Instead dependency instance will be injected into application from outside by some Framework”. DI make our application more loosely coupled and hence easy to test and extend in future. (After practical demonstration it will be much clearer.)

All major technologies have support for implementing DI now a days. These Technologies and frameworks have something called an “injector”. Injector at run time creates instance of dependency and make it available to the application.

Good news is, Angular have inbuilt support for Dependency injection which we will see in action very soon. Angular will creates an application-wide “Angular injector” during the bootstrap process. Once the Angular Service is created it will be registered with Angular injector. Angular injector creates the instance of this service and make it available to other parts.

Next two will make this concept very much clear.

Lab 11 – Decouple Application Logic from Component

In our project right now component specific logic and application logic both are written inside same class that is “AppComponent” class.

As a best practice we should take application specific logic out of the AppComponent class and should be put it in some independent class. Instance of that class will be injected into “AppComponent” by Angular framework at runtime. In short we have to implement DI in our Application.

Step 1 – Create Services Folder

Create a new folder called “Services” inside “AppModule” folder.

Step 2 – Create EmployeeService.

Now create a new TypeScript file called “EmployeeService.ts” in the “Services” folder.

Inside that TypeScript file create a class “EmployeeService” as follows.

import {Employee} from "../Models/Employee"

export class EmployeeService{
     Employees:Array<Employee>;
      constructor(){
        this.Employees =new Array<Employee>();
        
        let e1=new Employee();;
        e1.FName="Sukesh";
        e1.LName="Marla";
        e1.Salary=10000;
        this.Employees.push(e1);

        let e2=new Employee();;
        e2.FName="Gabbar";
        e2.LName="Singh";
        e2.Salary=20000;
        this.Employees.push(e2);
        
        let e3=new Employee();;
        e3.FName="Dragon";
        e3.LName="Hunter";
        e3.Salary=30000;
        this.Employees.push(e3);
    }
    GetEmployees():Array<Employee>{
        return this.Employees;
    }
    SaveEmployee(e:Employee){
        this.Employees.push(e);
    }
}

It’s a simple class with two methods.

  • GetEmployees – Return the list of employees
  • SaveEmployee – Which will add new Employee to the existing collection.

(It’s the same hard coded logic which is there in “AppComponent” class right now.)

Step 3 – Redefine AppComponent

Now it’s time to take application logic out of the AppComponent class.

Redefine it as follows.

import {Component} from "@angular/core"
import {Employee} from "../Models/Employee"
import {EmployeeService} from "../Services/EmployeeService"
@Component({
selector:'app-component',
templateUrl:'./app.component.html'
}
)
export class AppComponent{
    Employees:Array<Employee>;
    IsAddNew:boolean;
    constructor(private eLogic:EmployeeService){
        this.IsAddNew=false;
        this.Employees =this.eLogic.GetEmployees();
    }
    SaveEmployee():void{
       let e1=new Employee();
        e1.FName="F1";
        e1.LName="L1";
        e1.Salary=40000;
        this.eLogic.SaveEmployee(e1);
        this.IsAddNew=false;
    }
    ShowAddNew():void{
        this.IsAddNew=true;
    }
    HideAddNew():void{
        this.IsAddNew=false;
    }
}

You will following three things.

  1. All the employee related logical code is removed from AppComponent class to a new class called “EmployeeService”
  2. Constructor of AppComponent class is no more the Default constructor. It’s changed into Parametrized constructor. It is accepting the parameter of type “EmployeeService”.
  3. You won’t see any code creating “EmployeeService” instance. At runtime Angular creates the instance of EmployeeService class and pass it to the AppComponent constructor.

This is called “Dependency Injection” and hence “EmployeeService” is an injectable logic.

Step 4 – Test the application

Just switch focus to the command window running TypeScript compiler and make sure that there is no compile error.

F5

Get into the browser and check the new output.

F6

L

Step 5 – Define the provider

As I said before, Services need to be registered with Angular injector first. We haven’t done it yet.

It can be done either at Module level or at component level.

To register service we need to register the provider. Provider provides the concrete, runtime version of the dependency value. Injector relies on providers to create instances of the services that the injector injects into other parts of the application.

In this lab we will register Providers in Component level. Later in the future we will move it to Module level and understand the difference and advantage both.

Open app.component.ts and modify “Component” decorator as follows.

import {EmployeeService} from "../Services/EmployeeService"
@Component({
selector:'app-component',
templateUrl:'./app.component.html',
providers:[{provide:EmployeeService,useClass:EmployeeService}]
})
export class AppComponent{

Check the providers section in above code.

providers:[{provide:EmployeeService,useClass:EmployeeService}]

It means Angular injector will create instance of EmployeeService when other parts of the application ask for EmployeeService. It may seems illogical to you at this moment. “AppComponent is expecting EmployeeService and Angular Injector is creating and injecting EmployeeService”. What the point when both expecting and injecting things are same?  You will get to answer very soon.

Step 6 – Check the output

(Make sure your two command prompts are running. One with TypeScript compiler in watch mode and with lite-server.)

F7

Step 7 – Change the dependency

Now it’s time to see the power of Dependency injection. Simply create one more TypeScript file “EmployeeDummyService.ts” in Services folder with following content.

import {Employee} from "../Models/Employee"

export class EmployeeDummyService{
     Employees:Array<Employee>;
      constructor(){
        this.Employees =new Array<Employee>();
        
        let e1=new Employee();;
        e1.FName="Sukesh1";
        e1.LName="Marla1";
        e1.Salary=40000;
        this.Employees.push(e1);

        let e2=new Employee();;
        e2.FName="Gabbar2";
        e2.LName="Singh2";
        e2.Salary=50000;
        this.Employees.push(e2);
        
        let e3=new Employee();;
        e3.FName="Dragon3";
        e3.LName="Hunter4";
        e3.Salary=60000;
        this.Employees.push(e3);
    }
    GetEmployees():Array<Employee>{
        return this.Employees;
    }
    SaveEmployee(e:Employee){
        this.Employees.push(e);
    }
}

As you can see it have same structure as “EmployeeService”, only data is different.

Now in “Component” decorator, change provider as following.

import {Employee} from "../Models/Employee"
import {EmployeeService} from "../Services/EmployeeService"
import {EmployeeDummyService} from "../Services/EmployeeDummyService"
@Component({
selector:'app-component',
templateUrl:'./app.component.html',
providers:[{provide:EmployeeService,useClass:EmployeeDummyService}]
})
export class AppComponent{

It means Angular Injector creates instance of “EmployeeDummyService” and injects it when “EmployeeService” is expected.

Step 8 – Check the new output

Switch to browser and check the new output.

F8

As you can see now data is coming from newly created “EmployeeDumyyService”.

Now change provider back to EmployeeService and get project to original state.

As you can see now my application logic is completely decoupled from the component.

Summary

In case of any queries you can drop a comment. I will try best to reply earliest.

We are Mumbai based software development + Corporate Training firm. We have specialization in .net stack, Mean stack and PHP stack. For any inquiry visit www.justcompile.com or drop an email at SukeshMarla@Gmail.com

Comments

comments

%d bloggers like this: