Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

Angular services tutorial

Suggested Videos
Part 22 - Angular component output properties | Text | Slides
Part 23 - Interfaces in Angular 2 | Text | Slides
Part 24 - Angular component lifecycle hooks | Text | Slides

In this video we will discuss
  • Why we need a service in Angular
  • Creating a service in Angular
  • Injecting and using the service
  • Difference between constructor and ngOnInit


Why do we need a service in Angular
A service in Angular is generally used when you need to reuse data or logic across multiple components. Anytime you see logic or data-access duplicated across multiple components, think about refactoring that piece of logic or data-access code into a service. Using a service ensures we are not violating one of the Software principles - DRY ((Don't repeat yourself). The logic or data access is implemented once in a service, and the service can be used across all the components in our application. 



Without the service you would have to repeat your code in each component. Imagine the overhead in terms of time and effort required to develop, debug, test and maintain the duplicated code across multiple places instead of having that duplicated code at one central place like a service and reusing that service where required.

Creating a service in Angular : We will be working with the same example that we have been working with so far in this video series. Add a new TypeScript file to the "employee" folder and name it employee.service.ts. Copy and paste the following code. At the moment we have the data hard-coded in the service method. In a later video we will discuss retrieving data from a remote server using HTTP.

import { Injectable } from '@angular/core';
import { IEmployee } from './employee';

// The @Injectable() decorator is used to inject other dependencies
// into this service. As our service does not have any dependencies
// at the moment, we may remove the @Injectable() decorator and the
// service works exactly the same way. However, Angular recomends
// to always use @Injectable() decorator to ensures consistency
@Injectable()
export class EmployeeService {
    getEmployees(): IEmployee[] {
        return [
            {
                code: 'emp101', name: 'Tom', gender: 'Male',
                annualSalary: 5500, dateOfBirth: '6/25/1988'
            },
            {
                code: 'emp102', name: 'Alex', gender: 'Male',
                annualSalary: 5700.95, dateOfBirth: '9/6/1982'
            },
            {
                code: 'emp103', name: 'Mike', gender: 'Male',
                annualSalary: 5900, dateOfBirth: '12/8/1979'
            },
            {
                code: 'emp104', name: 'Mary', gender: 'Female',
                annualSalary: 6500.826, dateOfBirth: '10/14/1980'
            },
            {
                code: 'emp105', name: 'Nancy', gender: 'Female',
                annualSalary: 6700.826, dateOfBirth: '12/15/1982'
            },
            {
                code: 'emp106', name: 'Steve', gender: 'Male',
                annualSalary: 7700.481, dateOfBirth: '11/18/1979'
            },
        ];
    }
}

Injecting and using the service : We need the employee service we created above in EmployeeListComponent. So let's import, register and use the Employee service in EmployeeListComponent as shown below. 

// Import OnInit Life Cycle Hook interface
import { Component, OnInit } from '@angular/core';
import { IEmployee } from './employee';
// Import EmployeeService
import { EmployeeService } from './employee.service';

@Component({
    selector: 'list-employee',
    templateUrl: 'app/employee/employeeList.component.html',
    styleUrls: ['app/employee/employeeList.component.css'],
    // Register EmployeeService in this component by
    // declaring it in the providers array
    providers: [EmployeeService]
})
// Make the class implement OnInit interface
export class EmployeeListComponent implements OnInit {
    employees: IEmployee[];

    selectedEmployeeCountRadioButton: string = 'All';

    // Inject EmployeeService using the constructor
    // The private variable _employeeService which points to
    // EmployeeService singelton instance is then available
    // throughout this class
    constructor(private _employeeService: EmployeeService) {
    }

    // In ngOnInit() life cycle hook call the getEmployees()
    // service method of EmployeeService using the private
    // variable _employeeService
    ngOnInit() {
        this.employees = this._employeeService.getEmployees();
    }

    getTotalEmployeesCount(): number {
        return this.employees.length;
    }

    getTotalMaleEmployeesCount(): number {
        return this.employees
            .filter(e => e.gender === 'Male').length;
    }

    getTotalFemaleEmployeesCount(): number {
        return this.employees.filter(e => e.gender === 'Female').length;
    }

    onEmployeeCountRadioButtonChange(selectedRadioButtonValue: string): void {
        this.selectedEmployeeCountRadioButton = selectedRadioButtonValue;
    }
}

Please do not forget to use the EmployeeListComponent selector (list-employee) as a directive in the root component - AppComponent (app.component.ts) as shown below.

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

@Component({
    selector: 'my-app',
    template: `<list-employee></list-employee>`
})
export class AppComponent {
}

At this point, run the application and notice it works exactly the same way as before. 

The following line of code which calls the service, can be placed even in the constructor and the application still works exactly the same way as before. So what is the difference between a constructor and ngOnInit life cycle hook, and when to use one over the other.

this.employees = this._employeeService.getEmployees();

Difference between constructor and ngOnInit
A class constructor is automatically called when an instance of the class is created. It is generally used to initialise the fields of the class and it's sub classes. 

ngOnInit is a life cycle hook method provided by Angular. ngOnInit is called after the constructor and is generally used to perform tasks related to Angular bindings. For example, ngOnInit is the right place to call a service method to fetch data from a remote server. We can also do the same using a class constructor, but the general rule of thumb is, tasks that are time consuming should use ngOnInit instead of the constructor. As fetching data from a remote server is time consuming, the better place for calling the service method is ngOnInit.

So coming back to our example, the dependency injection is done using the class constructor and the actual service method call is issued from ngOnInit life cycle hook as shown below

constructor(private _employeeService: EmployeeService) { }

ngOnInit() {
    this.employees = this._employeeService.getEmployees();
}

In our next video we will discuss retrieving data from a remote server using HTTP.

Angular 2 tutorial for beginners

2 comments:

  1. I am getting following error. Please help


    ERROR TypeError: _co.getMaleEmployeesCount is not a function
    at Object.eval [as updateDirectives] (EmployeeListComponent.html:2)
    at Object.debugUpdateDirectives [as updateDirectives] (core.es5.js:13093)
    at checkAndUpdateView (core.es5.js:12270)
    at callViewAction (core.es5.js:12638)
    at execComponentViewsAction (core.es5.js:12570)
    at checkAndUpdateView (core.es5.js:12276)
    at callViewAction (core.es5.js:12638)
    at execComponentViewsAction (core.es5.js:12570)
    at checkAndUpdateView (core.es5.js:12276)
    at callWithDebugContext (core.es5.js:13493)

    ReplyDelete
  2. Issue resolved. Just restarted vs code.

    ReplyDelete

It would be great if you can help share these free resources