Angular Services Example using @Injectable()
September 30, 2021
This page will walk through Angular services example using @Injectable()
decorator. Angular services are injectable and injector can inject it in any component or service in our Angular application. The @Injectable()
decorator is used in service at class level. The @Injectable()
decorator helps the injector to consider the service eligible to inject. After configuring our service in providers
metadata of @NgModule
decorator in application module, the service becomes available globally.
To get instance of service in our component, we need to create a constructor with arguments of our service types. A service contains methods that can be used by components or other services.
Suppose, we want to create a shopping cart application. In this case, the service can contain methods to manage store items, methods to add item to cart, methods to remove item from cart, methods to search item etc.
Here in our example, we will create a simple shopping cart application. To fetch items, we will use HTTP and non HTTP mock data.
Now find the complete Angular services example step-by-step.
Contents
Technologies Used
Find the technologies being used in our example.1. Angular 12.1.0
2. Node.js 12.14.1
3. NPM 7.20.3
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 globally in the application.
We can also use
providedIn: 'root'
attribute in @Injectable
decorator to make available service globally.
@Injectable({ providedIn: 'root' }) export class ItemService { }
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 interface Item { id: number; name: string; price: string; description: string; }
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 { const item = ITEMS.find(ob => ob.id === id) ?? {} as Item; if (this.selectedItems.indexOf(item) < 0) { this.selectedItems.push(item); } } removeItem(id: number): void { const item = this.selectedItems.find(ob => ob.id === id) ?? {} as Item; const 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 { HttpClientModule } from '@angular/common/http'; 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, HttpClientModule ], declarations: [ AppComponent, StoreComponent, CartComponent ], providers: [ ItemService ], bootstrap: [ AppComponent ] }) export class AppModule { }
Angular Service with HTTP Request
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: HttpClient) { this.observableItems = this.http.get<Item[]>(this.url); this.observableItems.subscribe( data => this.allItems = data, error => this.errorMessage = 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 { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { Item } from './item'; @Injectable() export class ItemService { observableItems: Observable<Item[]>; allItems: Item[] = []; selectedItems: Item[] = []; errorMessage = ''; url = "http://localhost:4200/assets/data/products.json"; constructor(private http: HttpClient) { this.observableItems = this.http.get<Item[]>(this.url); this.observableItems.subscribe( data => this.allItems = data, error => this.errorMessage = error); } getItems(): Observable<Item[]> { return this.observableItems; } getSelectedItems(): Item[] { return this.selectedItems; } addItem(id: number): void { const item = this.allItems.find(ob => ob.id === id) ?? {} as Item; if (this.selectedItems.indexOf(item) < 0) { this.selectedItems.push(item); } } removeItem(id: number): void { const item = this.selectedItems.find(ob => ob.id === id) ?? {} as Item; const itemIndex = this.selectedItems.indexOf(item); this.selectedItems.splice(itemIndex, 1); } }
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[] = []; errorMessage = ''; constructor(private itemService: ItemService) { } getStoreItems(): void { this.itemService.getItems().subscribe( data => this.storeItems = data, error => this.errorMessage = 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
Run Application
To run the demo application, find following steps.1. Download source code using download link given below on this page.
2. Use downloaded src in your angular CLI application. To install angular CLI, find the link.
3. Run ng serve using command prompt.
4. Now access the URL http://localhost:4200
Find the print screen.
http://localhost:4200/

References
Angular: SERVICESAngular: @Injectable