Home  >  Angular

Angular 2 Services Example using @Injectable()

By Arvind Rai, April 02, 2017
This page will walk through angular 2 services example using @Injectable(). Angular services are injectable and injector can inject it in any component in our angular application. When we add our service in providers metadata of @NgModule in module file then the service becomes available globally in the application. To get instance of service in our component, we need to create a constructor with arguments of our service types in private scope. When we use @Injectable() decorator in service at class level then angular injector considers the service available to inject. A service contains methods that can be used by components. For example we want to create a shopping cart application then in this case, the service can contain method to provide store items, method to add item to cart, method to provide items for cart, method to remove item from cart, method to search item etc. In our example we will create a simple shopping cart application. To get items as JSON data, we will use HTTP and non HTTP mock data. We will create our angular application using angular CLI. Now find the complete angular services example step by step.


Software Used

Find the software used in our example.
1. Angular 4.0.0
2. TypeScript 2.2.0
3. Node.js 6.10.1
4. Angular CLI 1.0.0
5. Angular Compiler CLI 4.0.0

Steps to Create Angular Service

To create angular service we need to follow below steps.
Step-1: Create a class decorated with @Injectable()
@Injectable()
export class ItemService {
} 
@Injectable() decorator is a marker used at class level. It tells Injector that this class is available for creation by Injector. We use @Injectable() in our service class so that the service object can be created automatically for dependency injection in any component or any other service class. @Injectable() is also responsible to instantiate an angular component, pipe, directive etc. This becomes possible because @Component, @Pipe and @Directive decorators use @Injectable decorator. If our service class decorated with @Injectable() has dependency of other service classes, then we need not to worry for its creation and dependency injection will be performed by Injector automatically.

Step-2: Configure service name in providers metadata with @NgModule in module file.
@NgModule({
  ----
  ----
  providers: [
        ItemService
  ],
  ----
  ----
})
export class AppModule { } 
A component can use service only if we configure service in providers metadata of @NgModule. We can also configure service in providers metadata of @Component but in this case the service will be available to only this component. When we configure service in providers metadata of @NgModule decorator in module file then that service will be available to be injected anywhere in the application.

Step-3: Inject service in Component.
@Component({
   selector: 'store-app',
   templateUrl: './store.component.html' 
})
export class StoreComponent { 
   constructor(private itemService: ItemService) { }
} 
To get service available in our component we need to create a constructor with an argument of our service type in private scope. When component is loaded, service will be injected by the injector. Now we are ready to call service methods in our component. In the above code snippet, our service instance is itemService that will be used to call methods of ItemService service.

Angular Service Example with Shopping Cart

We will create an angular shopping cart application that will have one service and two components one for product store and another for cart. When the application will be loaded the store component will fetch items from the service and will display in its store front. When user will select item to add to cart, then item id will be passed to service from store component. Now service will add item into selected item that will be displayed by cart. When item needs to remove from cart then cart component will send item id to service and service will remove this item from selected items for cart.

1. Project Structure

Find the project structure.
angular-demo
|
|--src
|   |
|   |--app 
|   |   |
|   |   |--services
|   |   |   |
|   |   |   |--item.service.ts
|   |   |   |--item.ts
|   |   |   |--mock-items.ts   
|   |   |
|   |   |--store
|   |   |   |
|   |   |   |--store.component.ts
|   |	|   |--store.component.html
|   |	|   |--store.component.css
|   |   | 
|   |   |--cart    
|   |   |   |
|   |   |   |--cart.component.ts
|   |   |   |--cart.component.html
|   |   |   |--cart.component.css
|   |   |
|   |   |--app.component.ts
|   |   |--app.module.ts 
|   | 
|   |--main.ts
|   |--index.html
|   |--styles.css
|
|--node_modules
|--package.json 

2. Create Mock Data

To display product item in store front we are considering a JSON data. We will create an item class that will have item property related to product. We will create a constant that will store JSON data as an array of items. Find the item class.
services\item.ts
export class Item {
   id: number;
   name: string;
   price: string;
   description: string;
   constructor() { 
   }
} 
Find the constant file.
services\mock-items.ts
import { Item } from './item';

export const ITEMS: Item[] = [
  {"id": 1, "name": "Product 1", "price": "25.50", "description": "Product 1 description"},
  {"id": 2, "name": "Product 2", "price": "15.20", "description": "Product 2 description"},
  {"id": 3, "name": "Product 3", "price": "13.50", "description": "Product 3 description"},
  {"id": 4, "name": "Product 4", "price": "26.40", "description": "Product 4 description"},
  {"id": 5, "name": "Product 5", "price": "11.50", "description": "Product 5 description"},
  {"id": 6, "name": "Product 6", "price": "35.70", "description": "Product 6 description"}
]; 

3. Create Service

We will create service now. Create a class decorated with @Injectable().
services\item.service.ts
import { Injectable } from '@angular/core';
import { Item } from './item';
import { ITEMS } from './mock-items';

@Injectable()
export class ItemService {
    selectedItems: Item[] = [];
    getItems(): Item[] {
	return ITEMS;
    }
    getSelectedItems(): Item[] {
	return this.selectedItems;
    }	
    addItem(id:number): void {
       let item = ITEMS.find(ob => ob.id === id);
       if (this.selectedItems.indexOf(item) < 0) {	   
	      this.selectedItems.push(item);
       }
    }
    removeItem(id:number): void {
       let item = this.selectedItems.find(ob => ob.id === id);
       let itemIndex = this.selectedItems.indexOf(item);
       this.selectedItems.splice(itemIndex, 1);
    }
} 
In our service class we have created four methods.
getItems(): This is accessed by store component to display store items.
getSelectedItems(): This is accessed by cart component to display cart items.
addItem(): This is called by store component when "Add to Cart" button is clicked.
removeItem(): This is called by cart component when "Remove" button is clicked.

4. Create Components and HTML Templates

We will create two components and its HTML templates. One component will handle store front and another component will handle cart. Find the store component.
store\store.component.ts
import { Component, OnInit } from '@angular/core';
import { Item } from '../services/item';
import { ItemService } from '../services/item.service';

@Component({
  selector: 'store-app',
  templateUrl: './store.component.html', 
  styleUrls: ['./store.component.css']
})
export class StoreComponent implements OnInit { 
   storeItems: Item[] = [];
   constructor(private itemService: ItemService) { }
   getStoreItems(): void {
        this.storeItems = this.itemService.getItems();
   }
   ngOnInit(): void {
        this.getStoreItems();
   }
   addItemInCart(id:number): void {
	this.itemService.addItem(id);
   }
} 
store\store.component.html
<div [ngClass]="'leftPanel'">
        <h3>Store</h3>
	<div [ngClass]="'storeBox'" *ngFor="let item of storeItems" >
	  <div>
		<div >
		  <h4><a href="#">{{item.name}}</a></h4>
		  <h4 >Price:{{item.price}}</h4>
		  <p>{{item.description}}</p>
		</div>
		<div>
		  <button type="button" (click)="addItemInCart(item.id)">Add to Cart</button>
		</div>
	  </div>
	</div>
</div> 
store\store.component.css
.leftPanel{float:left; width:40%}
.storeBox{float:left; width:170px;}
.rightPanel{float:left;}

h3{font-size:20px;} 
Find the cart component.
cart\cart.component.ts
import { Component, OnInit } from '@angular/core';
import { Item } from '../services/item';
import { ItemService } from '../services/item.service';

@Component({
  selector: 'cart-app',
  templateUrl: './cart.component.html', 
  styleUrls: ['./cart.component.css']
})
export class CartComponent implements OnInit { 
   cartItems: Item[] = [];
   constructor(private itemService: ItemService) { }
   getItemsForCart(): void {
        this.cartItems = this.itemService.getSelectedItems();
   }
   ngOnInit(): void {
        this.getItemsForCart();
   }
   removeItemFromCart(id:number): void {
        this.itemService.removeItem(id);
   }
} 
cart\cart.component.html
<div [ngClass]="'rightPanel'">
  <h3>Cart</h3>
  <ul *ngFor="let item of cartItems">
	<li>
	  <span> {{item.name}} </span> 
	  <span><button type="button" (click)="removeItemFromCart(item.id)">Remove</button></span>
	</li>
  </ul>
</div> 
cart\cart.component.css
.leftPanel{float:left; width:40%}
.storeBox{float:left; width:170px;}
.rightPanel{float:left;}

h3{font-size:20px;} 

5. Create Application Component and Module

Find the angular module of our application. Here we will configure our service ItemService using providers metadata of @NgModule in our application module.
app.component.ts
import { Component } from '@angular/core';
@Component({
  selector: 'app-root',
  template: `              
			    <store-app> </store-app> 			   
			    <cart-app> </cart-app> 			  
           `
})
export class AppComponent { 
} 
app.module.ts
import {BrowserModule} from '@angular/platform-browser';
import {NgModule}      from '@angular/core';

import {StoreComponent}  from './store/store.component';
import {CartComponent}  from './cart/cart.component';
import {AppComponent}  from './app.component';
import {ItemService} from './services/item.service';

@NgModule({
  imports: [     
        BrowserModule
  ],
  declarations: [
        AppComponent, 
	StoreComponent,
	CartComponent
  ],
  providers: [
        ItemService
  ],
  bootstrap: [
        AppComponent
  ]
})
export class AppModule { } 

Angular Service with HTTP Example

Now we will create our shopping cart example using JSON data accessing from HTTP. In this example we will not use mock-items.ts file. Here we will access a URL using angular HTTP and populate data in store front. To enable HTTP, we need to add HttpModule in imports metadata of @NgModule in app.module.ts file. We will use HTTP in our service as follows.
observableItems: Observable<Item[]>
constructor(private http:Http) { 
   this.observableItems = this.http.get(this.url).map((res: Response) => res.json());
   this.observableItems.subscribe(
			 data => this.allItems = data,
			 error =>  this.errorMessage = <any>error);
}
getItems(): Observable<Item[]> {
   return this.observableItems;
} 
Find the description of HTTP API used in the above code snippet.
Observable: This is a stream of events that can be processed with array-like operators. Every HTTP service method returns an Observable.
http.get(): This access a HTTP URL using HTTP GET method and returns an Observable.
map(): This is a RxJS operator that extracts response object from response data.
subscribe(): It fetches events in the stream from Observable.

Now find the service and store component where we have done changes according to use HTTP method. Other files in our application will be same.
services\item.service.ts
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';
import { Item } from './item';

@Injectable()
export class ItemService {
        observableItems: Observable<Item[]>
	allItems: Item[] = [];
        selectedItems: Item[] = [];
	errorMessage: string;
	url = "http://localhost:4200/assets/data/products.json";
	constructor(private http:Http) { 
	   this.observableItems = this.http.get(this.url).map((res: Response) => res.json());
	   this.observableItems.subscribe(
	             data => this.allItems = data,
		     error =>  this.errorMessage = <any>error);
	}
	getItems(): Observable<Item[]> {
	   return this.observableItems;
	}
	getSelectedItems(): Item[] {
	   return this.selectedItems;
	}	
        addItem(id:number): void {
           let item = this.allItems.find(ob => ob.id === id);
           if (this.selectedItems.indexOf(item) < 0) {	   
	      this.selectedItems.push(item);
	   }
        }
        removeItem(id:number): void {
	   let item = this.selectedItems.find(ob => ob.id === id);
	   let itemIndex = this.selectedItems.indexOf(item);
           this.selectedItems.splice(itemIndex, 1);
        }
} 
store\store.component.ts
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Item } from '../services/item';
import { ItemService } from '../services/item.service';

@Component({
  selector: 'store-app',
  templateUrl: './store.component.html', 
  styleUrls: ['./store.component.css']
})
export class StoreComponent implements OnInit { 
   storeItems: Item[] = [];
   errorMessage: string;
   constructor(private itemService: ItemService) { }
   getStoreItems(): void {
	    this.itemService.getItems().subscribe(
		   data => this.storeItems = data,
		   error =>  this.errorMessage = <any>error);
   }
   ngOnInit(): void {
        this.getStoreItems();
   }
   addItemInCart(id:number): void {
	this.itemService.addItem(id);
   }
} 
To create a sample HTTP URL using Angular CLI, create a file products.json and put it inside src/assets/data . Now we are ready with our HTTP URL as given below.
http://localhost:4200/assets/data/products.json 
This will return product JSON data for store front.

Test Application

To test the application find the following steps.
1. Download the source code from the download link given on this page.
2. Place src in angular CLI application.
3. Open the command prompt and navigate to root directory of the project and run command ng serve .
4. Access the URL
http://localhost:4200/ 
and then add some items in cart. Find the print screen.
Angular 2 Services Example using @Injectable()

References

Angular: SERVICES
Angular: HTTP

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
FIND MORE TUTORILAS






©2019 concretepage.com | Privacy Policy | Contact Us