AngularJS 2.0 From The Beginning - Service (Day 11)

I am here to continue the discussion around AngularJS 2.0.  So far we have discussed about data binding, input properties, output properties, pipes, viewchild, and also about directives in Angular 2.0. Now in this article, I will discuss how to create a Service in Angular 2.0. Also, in case you did not have a look at the previous articles of this series, go through the links mentioned below.

An Angular 2 Service is simply a JavaScript function, including its related properties and methods which can perform a particular task or a group of tasks. Actually, Service is a mechanism to use shared responsibilities within one or multiple components. As we already know, we can create components in Angular 2 and nest multiple components together within a component using selector, once our components are nested, we need to manipulate some data within the multiple components. In this case, Service is the best way to handle the situation. Service is the best place where we can take data from other sources or write down some calculations. Similarly, Service can be shared between multiple components as per our need.

Angular 2.0 has greatly simplified the concept of Service over Angular 1.x. In Angular 1, there were service, factory, provider, delegate, value etc. and it was not always clear when to use which one. Angular 2 simply changes the concept of Service. There are two steps for creating a Service in Angular 2.0. 

  1. Create a class with @Injectable decorator.
  2. Register the class with provider or inject the class by using dependency injection. 

@Injectable

@Injectable is actually is a decorator. Decorators are a proposed extension in JavaScript. In short, decorator provides the facility of modifying or using methods, classes, properties and parameters. Injectables are just normal classes (normal objects) and as such, they have no special lifecycle. When an object of your class is created, the class’s constructor is called, so that’s what your “OnInit” would be.

As for the destruction, a service does not really get destroyed. The only thing that might happen is that it gets garbage collected once there is no longer a reference to it, which likely happens after the dependency injector is removed itself. But you generally have no control over it, and there is no concept of a deconstructor in JavaScript.
 
@Injectable() lets Angular know that a class can be used with the dependency injector. @Injectable() is not strictly required if the class has other Angular decorators on it or does not have any dependencies. What is important is that any class that is going to be injected with Angular is decorated. However, the best practice is to decorate injectables with @Injectable(), as it makes more sense to the reader.  
  1. @Injectable()  
  2. export class SampleService {  
  3.     constructor() {  
  4.         console.log('Sample service is created');  
  5.     }  
  6. }  

What is Dependency Injection?

Actually, dependency injection is an important and useful application design pattern. Angular 2.0 has its own dependency injection framework. Basically, it is a coding pattern in which classes receive their dependencies from external sources rather than creating them.

Dependency Injection in Angular 2.0

Dependency injection has always been one of Angular’s biggest features and selling points. It allows us to inject dependencies in different components across our applications, without needing to know how those dependencies are created, or what dependencies they need themselves. However, it turns out that the current dependency injection system in Angular 1.x has some problems that need to be solved in Angular 2.x, in order to build the next generation framework. 

Dependency Injection basically consists of three things, 

  1. Injector – The Injector object that exposes APIs to us to create instances of dependencies
  2. Provider – A Provider is like a commander that tells the injector how to create an instance of a dependency. A provider takes a token and maps that to a factory function that creates an objects.
  3. Dependency – A Dependency is the type of which an object should be created. 
Now, for demonstrating the Service, we will create a Service called StudentService which is basically storing the student details data. When we add any new student information from entry form, that data is also included in the StudentService. Also, on requirement, we can retrieve all the students list from the Service. For this purpose, we need to add a TypeScript file called app.service.student.ts and add the below code.
  1. import { Injectable } from "@angular/core";  
  2.   
  3. @Injectable()  
  4. export class StudentService {  
  5.     private _studentList: Array<any> = [];  
  6.   
  7.     constructor() {  
  8.         this._studentList = [{name:'Amit Roy', age:20, city:'Kolkata', dob:'01-01-1997'}];  
  9.     }  
  10.   
  11.     returnStudentData(): Array<any> {  
  12.         return this._studentList;  
  13.     }  
  14.   
  15.     addStudentData(item: any): void {  
  16.         this._studentList.push(item);  
  17.     }  
  18. }  
In the above Service, we defined a private array type variable called "_studentList" which basically stores all the students details. Also, we created two public methods named returnStudentData (for fetching student list from component) and addStudentData for new students' entry within the list.
 
Now, we need to define the student form component. For this, we need to add an HTML file named app.component.student.html and add the below code.
  1. <div>  
  2.     <h2>Student Form</h2>  
  3.     <table style="width:80%;">  
  4.         <tr>  
  5.             <td>Student Name</td>  
  6.             <td><input type="text" [(ngModel)]="_model.name" /></td>  
  7.         </tr>  
  8.         <tr>  
  9.             <td>Age</td>  
  10.             <td><input type="number" [(ngModel)]="_model.age" /></td>  
  11.         </tr>  
  12.         <tr>  
  13.             <td>City</td>  
  14.             <td><input type="text" [(ngModel)]="_model.city" /></td>  
  15.         </tr>  
  16.         <tr>  
  17.             <td>Student DOB</td>  
  18.             <td><input type="date" [(ngModel)]="_model.dob" /></td>  
  19.         </tr>  
  20.         <tr>  
  21.             <td></td>  
  22.             <td>  
  23.                 <input type="button" value="Submit" (click)="submit()" />     
  24.                 <input type="button" value="Reset" (click)="reset()" />  
  25.             </td>  
  26.         </tr>  
  27.     </table>  
  28.     <h3>Student Details</h3>  
  29.     <div class="ibox-content">  
  30.         <div class="ibox-table">  
  31.             <div class="table-responsive">  
  32.                 <table class="responsive-table table-striped table-bordered table-hover">  
  33.                     <thead>  
  34.                         <tr>  
  35.                             <th style="width:40%;">  
  36.                                 <span>Student's Name</span>  
  37.                             </th>  
  38.                             <th style="width:15%;">  
  39.                                 <span>Age</span>  
  40.                             </th>  
  41.                             <th style="width:25%;">  
  42.                                 <span>City</span>  
  43.                             </th>  
  44.                             <th style="width:20%;">  
  45.                                 <span>Date of Birth</span>  
  46.                             </th>  
  47.                         </tr>  
  48.                     </thead>  
  49.                     <tbody>  
  50.                         <tr *ngFor="let item of _source; let i=index">  
  51.                            <td><span>{{item.name}}</span></td>  
  52.                             <td><span>{{item.age}}</span></td>  
  53.                             <td><span>{{item.city}}</span></td>  
  54.                             <td><span>{{item.dob}}</span></td>  
  55.                         </tr>  
  56.                     </tbody>  
  57.                 </table>  
  58.             </div>  
  59.         </div>  
  60.     </div>  
  61.   
  62. </div>  
Now, add another TS file named app.component.student.ts and add the below code.
  1. import { Component, OnInit, ViewChild } from '@angular/core';  
  2. import { StudentService } from './app.service.student';  
  3.   
  4. @Component({  
  5.     moduleId: module.id,  
  6.     selector: 'student',  
  7.     templateUrl: 'app.component.student.html',  
  8.     providers: [StudentService]  
  9. })  
  10.   
  11. export class StudentComponent implements OnInit {  
  12.   
  13.     private _model: any = {};  
  14.     private _source: Array<any>;  
  15.   
  16.     constructor(private _service: StudentService) {  
  17.         this._source = this._service.returnStudentData();  
  18.     }  
  19.   
  20.     ngOnInit(): void {  
  21.     }  
  22.   
  23.     private submit(): void {  
  24.         if (this.validate()) {  
  25.             this._service.addStudentData(this._model);  
  26.             this.reset();  
  27.         }  
  28.     }  
  29.   
  30.     private reset(): void {  
  31.         this._model = {};  
  32.     }  
  33.   
  34.     private validate(): boolean {  
  35.         debugger;  
  36.         let status: boolean = true;  
  37.         if (typeof (this._model.name) === "undefined") {  
  38.             alert('Name is Blank');  
  39.             status = false;  
  40.             return;  
  41.         }  
  42.         else if (typeof (this._model.age) === "undefined") {  
  43.             alert('Age is Blank');  
  44.             status = false;  
  45.             return;  
  46.         }  
  47.         else if (typeof (this._model.city) === "undefined") {  
  48.             alert('City is Blank');  
  49.             status = false;  
  50.             return;  
  51.         }  
  52.         else if (typeof (this._model.dob) === "undefined") {  
  53.             alert('dob is Blank');  
  54.             status = false;  
  55.             return;  
  56.         }  
  57.         return status;  
  58.     }  
  59. }  
In this above component, we used provider attribute for injecting the StudentService within the component.
 
Now, add another TypeScript file named app.module.ts and add the below code.
  1. import { NgModule } from '@angular/core';  
  2. import { BrowserModule } from '@angular/platform-browser';  
  3. import { FormsModule } from "@angular/forms";  
  4. import { StudentComponent } from './src/app.component.student';  
  5.   
  6. @NgModule({  
  7.     imports: [BrowserModule, FormsModule],  
  8.     declarations: [StudentComponent],  
  9.     bootstrap: [StudentComponent]  
  10. })  
  11. export class AppModule { }  
Now, add another TypeScript file named main.ts and add the below code.
  1. import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';  
  2.   
  3. import { AppModule } from './app.module';  
  4.   
  5. const platform = platformBrowserDynamic();  
  6. platform.bootstrapModule(AppModule);  
Now, add another HTML file named index.html and add the below code.
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <title>Angular2 - Service</title>  
  5.     <meta charset="UTF-8">  
  6.     <meta name="viewport" content="width=device-width, initial-scale=1">  
  7.     <link href="../resources/style/style1.css" rel="stylesheet" />  
  8.     <!-- Polyfill(s) for older browsers -->  
  9.     <script src="../node_modules/core-js/client/shim.min.js"></script>  
  10.     <script src="../node_modules/zone.js/dist/zone.js"></script>  
  11.     <script src="../node_modules/reflect-metadata/Reflect.js"></script>  
  12.     <script src="../node_modules/systemjs/dist/system.src.js"></script>  
  13.     <script src="../systemjs.config.js"></script>  
  14.     <script>  
  15.         System.import('app').catch(function (err) { console.error(err); });  
  16.     </script>  
  17. </head>  
  18. <body>  
  19.     <student>Loading</student>  
  20.       
  21. </body>  
  22. </html>  
Now, when we  run the index.html file in the browser, we get the following output.