Angular 2 Services Example using @Injectable()
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.
Contents
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 { }
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) { } }
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() { } }
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); } }
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); } }
<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>
.leftPanel{float:left; width:40%} .storeBox{float:left; width:170px;} .rightPanel{float:left;} h3{font-size:20px;}
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); } }
<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>
.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 serviceItemService
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 { }
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 usemock-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; }
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); } }
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); } }
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
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/

References
Angular: SERVICESAngular: HTTP