Click here to Skip to main content
13,900,017 members
Click here to Skip to main content
Add your own
alternative version

Stats

10.5K views
223 downloads
14 bookmarked
Posted 8 Nov 2017
Licenced CPOL

Learn Angular Tutorial - Part 6

, 8 Nov 2017
Rate this:
Please Sign up or sign in to vote.
This is Lab 6 of Step by step Angular series.In this article we will cover two important labs Pipes and Providers.

 

Contents :-

Link to rest of the article
Introduction
Lab 13:- Pipes in Angular

Lab 14:- Providers , Services and Dependency Injection

Link to rest of the article

Introduction

In this article we will cover two important labs Pipes and Providers. Pipes helps us to create reusable code by which we can format outputs and providers help us to create good architecture for Angular.

Lab 13:- Pipes in Angular

This lab is the smallest of all labs till now with some theory followed by three steps. So if you are tired and worn out till now , this lab is like a restful lab.

Introduction

Pipes takes in a data input and transforms data to a different output. For example, pipe can take “Learn Angular” as input and transform to “LEARN ANGULAR” in capital or you can give input as “100” which you want to display (transform) as “100.00 $” on UI.

So for this lab we will do the following pipe transforms: -

  • Change Customer name in to capital letters.
  • Change Customer amount to proper formatted amount with $ currency sign.
  • Depending on the Amount we would like to display “Gold” or “Silver” customer status. So if the amount exceeds 100 it will display “Gold Customer” and if less than 100 it will display “Simple Customer”.

See the image for more detail of how the output would look like.

Understanding syntax of pipes

Before we move ahead with labs on pipes lets understand how the syntax of pipes looks like. You need to write pipe syntax inside an expression “{{ }}”. You need to first put data that needs to be formatted and then followed by “|” symbol as shown in the below figure. Once you run it, it displays final formatted output on the HTML.

Pipe syntaxes are written inside HTML.

Step 1 :- Applying readymade pipes

There are two broader categories of pipes:- Readymade pipes and Custom pipes. You can get list of readymade pipes from https://angular.io/api?type=pipe.

So to display “CustomerName” in capital and “CustomerAmount” with currency sign we can use two readymade filters “uppercase” and “currency” respectively. Below are the code syntaxes for the same.

{{CurrentCustomer.CustomerName | uppercase}}
{{CurrentCustomer.CustomerAmount | currency}}

Step 2 :- Creating custom pipes for customer grading

But the third requirement is a bit complicated. In this is the entered amount is greater than 100 we need to display “Gold Customer” and if it’s less than 100 we need to display “Normal Customer”.

So let’s create a separate folder called as “Pipes” and in that lets create “GradePipes.ts” as shown in the below figure.

In “GradePipes.ts” we will write the code which will have the logic. So first thing we need to import “Pipe” and “PipeTransform” from core as these classes are the building blocks for pipes.

import { Pipe, PipeTransform } from '@angular/core';

The next thing is we need to create a “GradePipes” class which implements the “PipeTransform” interface and has “@Pipe” decorated on the top of it. Every pipe class should have a “transform” method as it is small “t” “r”… “transform” which has a input parameter i.e. customer amount which will be provided in the UI.

@Pipe({name: 'GradePipes'})
export class GradePipes implements PipeTransform {
  transform(value:number): string {
        if(value < 100){

            return "Simple Customer";

        }

        else{

            return "Gold Customer";

        }

  }

}

In “@Pipe” decorator we have also specified a “name”. This name will be used in the UI to make call to the pipe.

Step 3 :- Applying the grading pipe on the UI

And then finally we need to call the pipe in the HTML UI. We need can now call “GradePipes” as shown in the below code. “CurrentCustomer.CustomerAmount” is the input and the pipe is “GradePipes”.

{{ CurrentCustomer.CustomerAmount|GradePipes}}

Once done Enjoy your output.

Lab 14:- Providers , Services and Dependency Injection

The Problem

Courtesy :- https://medium.com/nestle-usa/4-tips-for-starting-your-baby-on-fruits-veggies-aafd6b2c0cde

A sign of a good software architecture is :-

“When you make change at one place you do not need to change at many places”.

Now take the below situation. In your project let’s say you have lot of modules and 100’s (just put a figure 😊 ) components. Now in all your 100 components you want to implement logging utility.

In logging utility also you have different varieties. Some logger just logs to the console of the browser while some display using dialog boxes.

So assume that these loggers are used in those 100’s of components to log error and instrumentation messages. So in all your components you will do two things: -

  • Import the logger component using “import” syntax.
  • And then create object of the logger.

Below is the code snippet for it.

import { ConsoleLogger} from "../Utility/Utility"
// code deleted for clarity
export class CustomerComponent {
    logger: ConsoleLogger = new ConsoleLogger ();
    // code removed for clarity
}

Now let’s say somewhere down the line you think you want to log messages using dialog boxes , think about the amount of changes you need to make in your 100 of components.

Solution DI and IOC

Lets conclude what is the cause which leads to change in all components. To solve this problem below is the solution , read the below sentence slowly with full senses alive.

“The problem is because Component is creating the object of Utility , if we can INVERT this , means if we can inject / provide “Utility” to the components rather than creating , then this will make our architecture better”.

In other words, we need to implement “Inversion of control”. Means invert the object creation to someone else and component just refers a generic utility reference.

So rather than components creating the object of the utility component will ASK for providing/ injecting the “logger” object via constructor.

IOC is a concept and to implement IOC we need to use DI. I would encourage you to see this youtube video which explains DI and IOC in detail https://www.youtube.com/watch?v=FuAhnqSDe-o

So now that we know DI and IOC concepts, let’s do a demonstration for the same.

Demo of DI IOC

Here is a simple demo we will implement in our project to see the importance of Provider DI. So we will create a simple parent “Logger” class and we will create two flavour’s one which displays messages one on dialog boxes and other to the console of the browser.

We will then try to figure out how easy its to make changes at one place and replicate it across all places.

Step 1 :- Create the logger utility classes with Injectable attribute

So let’s create a folder called as “Utility” inside which we will create these logger classes.

Let’s create a parent “Logger” class from which we will inherit and create different flavours of “Logger” class. Now because this class will be injected in to the components we need to mark it with “@Injectable()” decorator. “@Injectable()” decorator is available in “Injectable” in “angular/core”.

import { Injectable } from '@angular/core';
@Injectable()
export class Logger{
   public  Log(){
    // some default logging
   }
}

Below is the code for “ConsoleLogger” and “DialogLogger” classes which inherit from “Logger” class. For now both classes do not have any functionality as such. At this moment lets focus on DI rather than logging functionality.

@Injectable()
export class ConsoleLogger extends Logger{
    public Log(){
        // do console logging here
    }
}
@Injectable()
export class DialogLogger extends Logger{
    public Log(){
        // do console logging here
    }
}

Step 2 :- Define providers and injection in the modules

So as we discussed previously the goal is that we want to change at one place and the logger types should change in all components.

Now the whole loading (bootstrapping) of our project starts with “MainModuleLibrary” , so if we can inject at the level of “MainModuleLibrary’ it will be available to all components and modules down below.

In the “MainModuleLibrary” using “@NgModule” decorator we need to provide the providers which will be trickled down to all components. In providers we need to specify two things: -

  • First the parent class which be referred in all components. So using the “provide” we have specified “Logger” class.
  • Second need to provide which child implementation object we want to inject in all components. That’s provided in “useClass”.
providers: [
      {
        provide: Logger,
        useClass: ConsoleLogger
      }
    ]

The complete code of the main module with “providers” looks something as shown below.

// Imports have been removed for clarity
import {Logger,DialogLogger,ConsoleLogger} from "../Utility/Utility"
@NgModule({
    imports: [RouterModule.forRoot(ApplicationRoutes), 
            HttpModule, 
            InMemoryWebApiModule.forRoot(CustomerApiService),
             BrowserModule,
             FormsModule,
             ReactiveFormsModule],
    declarations: [
                    MasterPageComponent,
                WelcomeComponent],
    bootstrap: [MasterPageComponent],
    providers: [
      {
        provide: Logger,
        useClass: ConsoleLogger
      }
    ]
})
export class MainModuleLibrary { }

Step 3 :- Define constructors for injection

Now that we have define on the main module which object will inject. In the components we need to expose the “logger” class in the constructor for DI purpose.

Note :- All your components should only refer “Logger” parent class and not the child classes. You can see in the below code we have imported only “Logger” class and through constructor only “logger” class is referred.

// code removed for clarity
import {Logger} from "../Utility/Utility"
@Component({
    templateUrl: "../UI/Customer.html"
})
export class CustomerComponent {
    constructor(public http:Http , logger:Logger){
        this.Display();
    }
// code removed for clarity
}

Step 4 :- Test if things are working

Run the application put a debug point and see the “ConsoleLogger” object getting injected. If you change it to “DialogLogger” you will see the same injected.

Take a deep breathe , close your eyes and think . You are changing in the main module and its getting propogated all over. As we started this lab saying a “Good architecture is all about changing at one place and the changes are reflected through out”.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author


You may also be interested in...

Comments and Discussions

 
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web04 | 2.8.190306.1 | Last Updated 8 Nov 2017
Article Copyright 2017 by Shivprasad koirala
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid