Monday, February 13, 2017

Services and dependency injection in angular 2



Service

  • Is a class with a focused purpose
  • Used for features that
    • Are independent from any particular component
    • Provides shared data or logic across components
    • Encapsulates external interactions

There are 2 ways our components can work with the service

  1st approach

  • Components can create an instance of the class and use it
          Drawback of this approach is that instance is local so we cant share data or other resources and it would be difficult to mock the service for testing

2nd approach

  • We can register the service with angular. 
  • Angular then creates an single instance of the service class called as singleton
  • Angular provides a built in injector which maintains the container of the created service instances. It manages the single instance for each registered service as require

Dependency injection

Def: A coding pattern in which a class receives the instances of objects it needs (called dependencies)
from an external source rather than creating them itself

If a component needs a service then the component defines the service as a dependency
Angular injector then injects the service class instance when the component class is instantiated. This process is called dependency injection

This the recommended way of using services


While using services we need to use the @Injectable decorator. This decorator is optional. Its a best practice to add it

Creating product service

import {Injectable } from '@angular/core';
import { IProduct } from './product';
@Injectable
export class ProductService{
    
    getProducts():IProduct[]{
        return [
                    {
                      "productId": 1,
                      "productName": "Leaf Rake",
                      "productCode": "GDN-0011",
                      "releaseDate": "March 19, 2016",
                      "description": "Leaf rake with 48-inch wooden handle.",
                      "price": 19.95,
                      "starRating": 3.2,
                      "imageUrl": "http://openclipart.org/image/300px/svg_to_png
                             /26215/Anonymous_Leaf_Rake.png"
                  },
                  {
                      "productId": 2,
                      "productName": "Garden Cart",
                      "productCode": "GDN-0023",
                      "releaseDate": "March 18, 2016",
                      "description": "15 gallon capacity rolling garden cart",
                      "price": 32.99,
                      "starRating": 4.2,
                      "imageUrl": "http://openclipart.org/image/300px/
                       svg_to_png/58471/garden_cart.png"
                  }
 ];
    }   

}

To register a service we should register a provider.
  • Provider is code that can create and return a service, typically the service class itself
  • We define it as a part of component or Angular module metadata
  • If we register a provider in a components metadata then angular injector can inject the service into the component and any of its children. We should take care to register the provider at appropriate level of the component tree
  • If a register a provider in an angular module the service is registered with the angular injector at the applications root making the service available everywhere in the application


When the class is constructed the angular injector sets this parameter to the injected instance of the requested service. We then assign the injected service instance to our local variable

Using product services in the product list


import {Component, OnInit} from '@angular/core';
//Import interface
import {IProduct} from './product';
//view for the component
import { ProductService } from './product.service';
@Component({
    selector:'pm-products',
    templateUrl:'app/products/product-list.component.html',
    styleUrls: ['app/products/product-list.component.css'] ,
     providers:[ProductService]   

})
//class
export class ProductListComponent implements OnInit{
     pageTitle:string='Product List';
     imageWidth:number=50;
     imageMargin:number=2;
     showImage:boolean=false;
     listFilter:string;
     products:IProduct[];
 constructor(private _productService:ProductService){

 }
 //functions
 toggleImage():void{
     this.showImage=!this.showImage;
 }
 //ngOnInit
 ngOnInit():void {
     console.log('In OnInit');
     this.products=this._productService.getProducts()
 }
onRatingClicked(message: string): void {
        this.pageTitle = 'Product List: ' + message;
    }
}

Output

No comments:

Post a Comment