Click here to Skip to main content
13,866,995 members
Click here to Skip to main content
Add your own
alternative version

Stats

9.6K views
361 downloads
6 bookmarked
Posted 22 Sep 2017
Licenced CPOL

Learn Angular Tutorial - Part 4

, 22 Sep 2017
Rate this:
Please Sign up or sign in to vote.
This is part 4 of Learn Angular tutorial. In this article we will understand how to make HTTP calls and how to create custom Angular components using Input and Outputs.

 

Contents

Lab 9:- Making HTTP calls

Lab 10:- Input, Output and emitters

Whats in the Next article?

Links to rest of the articles

Lab 9:- Making HTTP calls

Importance of server side interaction

HTML user interfaces are dead if there is no server side interaction. Normally in a web application we would like to send the data entered by end user to the server. On server side we would have some kind of service which can be created in technologies like Java , C# and so on. The server side technology can save, edit or delete this data in a database.

In simple words we need to understand how to make HTTP calls from Angular code to a server side technology.

Yes, this is a pure Angular article

I intend to keep this article as a pure Angular article. So teaching server side technology like ASP.NET MVC , Java services , PHP is out of scope.

So the server side service would be FAKED (Mocked) by using “Angular inmemory Webapi”. Please note this is not a service which you will use for production its only for test and development purpose.

In case you want to learn ASP.NET MVC you can start from this video https://www.youtube.com/watch?v=Lp7nSImO5vk

 

Step 1 :- Creating a fake server side service

Even though we have decided that we will not be creating a professional server side service using ASP.NET , Java etc but we will still need one. So we will be using a fake service called as “Angular in-memory web api”.

Already the “Angular inmemory web api” has been installed when we did npm. You can check your “package.json” file for the entry of “angular inmemory web api”.

Already the “Angular inmemory web api” has been installed when we did npm. You can check your “package.json” file for the entry of “angular inmemory web api”.

So let’s create a folder called as “Api” and in that lets add “CustomerApi.ts” file and in this file we will write code which will create a fake customer service.

On this fake service we will make HTTP calls.

Below is a simple service created using “angular-in-memory” open source. In this service we have loaded a simple “customers” collection with some sample customer records.

import { InMemoryDbService } from 'angular-in-memory-web-api'
import {Customer} from "../Model/Customer"
export class CustomerApiService implements InMemoryDbService {
  createDb() {
    let customers =[
      { CustomerCode: '1001', CustomerName: 'Shiv' , CustomerAmount :100.23 },
      { CustomerCode: '1002', CustomerName: 'Shiv1' , CustomerAmount :1.23 },
      { CustomerCode: '1003', CustomerName: 'Shiv2' , CustomerAmount :10.23 },
      { CustomerCode: '1004', CustomerName: 'Shiv3' , CustomerAmount :700.23 }
    ]
    return {customers};
  }
}

So now when angular makes HTTP call it will hit this in-memory API.

So when you make a HTTP GET it will return the above four records. When you make a HTTP POST it will add the data to the in-memory collection.

In other words we do not need to create a professional server side service using ASP.NET or Java service.

 

Step 2 :- Importing HTTP and WebAPI module in to main module

The next step is to import “HttpModule” from “angular/http” and in-memory API in to main module. Remember module is collection of components. So the “MainModule” has “CustomerComponent” , “SupplierComponent”, “MasterpageComponent” and “WelcomeComponent”.

import { HttpModule} from '@angular/http';
import {CustomerApiService} from "../Api/CustomerApi"

Also in the “NgModule” attribute in imports we need to specify “HttpModule” and “InMemoryWebApiModule”.

@NgModule({
    imports: [….
        HttpModule, 
        InMemoryWebApiModule.forRoot(CustomerApiService),
             …..],
    declarations: […],
    bootstrap: [….]
})
export class MainModuleLibrary { }

Shiv:- Talk about the sequence of the Httpmodule and Angular Webapi

Where do we put the HTTP call ?

The next question comes which is the right place to put HTTP calls ?.

So if you see the normal architecture of Angular it is as follows: -

  • User interface is binded with the Angular component using bindings ”[()]”.
  • So once end user starts putting data in the UI the model object (in our case it’s the customer object) will be loaded and sent to the Customer component.
  • Now customer component has the filled customer object. So the right place to make HTTP call is in the component.

Step 3 :- Importing HTTP in the Customer component

So let’s go ahead and import the Angular HTTP inside the Customer component.

import { Http, Response, Headers, RequestOptions } from '@angular/http';

We do not need to create object of HTTP using the new keyword, it will be dependency injected via the constructor. So on the constructor component we have defined the object injection of HTTP.

constructor(public http:Http){
    }

Step 4:- Creating header and request information

When we send HTTP request from client to server or we get response, header information is passed with the request and response. In header information we have things like content types, status, user agent and so on.

 

So to create a request we need to first create a header and using that header create a request. One of the header information we need to provide is type of content we are sending to server is it XML , JSON etc.

Below is how to create a simple request using basic header information.

let headers = new Headers({'Content-Type': 'application/json'});
let options = new RequestOptions({ headers: headers });

Step 5 :- Making HTTP calls and observables

Angular HTTP uses something called as observables. So angular is an observer and it subscribes to observable like HTTP response. In other words, its listening to data coming from the server.

So the below code says that we will be making a GET call to “api/customers” URL and when the data comes we will send the successful data to the “Success” function and when error occurs we will get it in “Error” function.

var observable = this.http.get("api/customers",  options);
        observable.subscribe(res => this.Success(res),
            res => this.Error(res));

Below is the code of Error and Success function. In “Success” function we are converting the response to JSON and assigning it to “Customers” collection which is in the component. If we have error we are displaying it in the browser console.

Error(err) {
        console.debug(err.json());
    }
    Success(res) {
        this.Customers = res.json().data;
    }

Step 6 :- Creating a simple post and get call

With all that wisdom we have gathered from Step 4 and Step 5 lets write down two functions one which will display data and the other which will post data.

Below is a simple “Display” function which makes a HTTP GET call.

Display(){   
        let headers = new Headers({
            'Content-Type': 'application/json'
        });
        let options = new RequestOptions({ headers: headers });
        var observable = this.http.get("api/customers",  options);
        observable.subscribe(res => this.Success(res),
            res => this.Error(res));
    }

As soon as the customer UI is loaded the customer component object will be created. So in the constructor we have called the “Display” function to load the customers collection.

export class CustomerComponent {
// other code removed for clarity
constructor(public http:Http){
            this.Display();
    }
// other codes removed for clarity
}

Below is simple “Add” function which makes a POST call to the server. In http POST call code below you can see customer object sent as the third parameter. After the “Add” call we have made call to “Display” so that we can see the new data added on the server.

Add(){
           let headers = new Headers({
            'Content-Type': 'application/json'
        });
        var cust:any = {};
        cust.CustomerCode = this.CurrentCustomer.CustomerCode;
        cust.CustomerName = this.CurrentCustomer.CustomerName;
        cust.CustomerAmount = this.CurrentCustomer.CustomerAmount;
        let options = new RequestOptions({ headers: headers });
        var observable = this.http.post("api/customers",cust,  options);
        observable.subscribe(res => this.Success1(res),
            res => this.Error(res));
        this.Display();
    }

In the above “Add” function you can see the below code which creates a fresh light weight customer object. So why do we need to create this fresh new object ?.

var cust:any = {};
cust.CustomerCode = this.CurrentCustomer.CustomerCode;
cust.CustomerName = this.CurrentCustomer.CustomerName;
cust.CustomerAmount = this.CurrentCustomer.CustomerAmount;

The current customer object has lot of other things like validations , prototype object etc. So posting this whole object to the server does not make sense. We just want to send three properties “CustomerCode”, “CustomerAmount” and “CustomerName”.

In other words we need to create a light weight DTO ( Data transfer object ) which just has those properties.

Step 7 :- Connecting components to User interface

Now that our component is completed we need to attach the “Add” function to the button using the “click” event of Angular. You can see that the (click) is inside a round bracket , in other words we are sending something(event click) from UI to the Object.

<input type="button" 

value="Click" (click)="Add()" [disabled]="!(CurrentCustomer.formGroup.valid)"/>

Also we need to create a table in which we will use “ngFor” loop and display the customers collection on the HTML UI. In the below code we have created a temporary object “cust” which loops through the “Customers” collection and inside tag we are using the expressions ({{cust.CustomerName}}) to display data.

<table>
    <tr>
        <td>Name</td>
         <td>code</td>
          <td>amount</td>
    </tr>
      <tr *ngFor="let cust of Customers">
        <td>{{cust.CustomerName}}</td>
         <td>{{cust.CustomerCode}}</td>
          <td>{{cust.CustomerAmount}}</td>
    </tr>
</table>

Go ahead and run the application. If you go and add “customer” object you should see the HTTP calls happening and the list getting loaded in the HTML table.

Lab 10:- Input, Output and emitters

Theory

Reusability is one of the most important aspects of development. As Angular is a UI technology we would like to create UI controls and reuse them in different UI.

For example in the Customer UI we have the table grid display. If we want to create grid in other UI we need to again repeat the “<tr><td>” loop. It would be great if we can create a generic reusable grid control which can be plugged in to any UI.

 

If we want to create a GENERIC reusable grid control you need to think GENERICALLY, you need to think in terms of INPUTS and OUTPUTS.

So if you are using this grid control with a Customer UI you get a Customer collection, if you are using a Supplier UI you will get a supplier collection.

 

In order to achieve this generic thought process Angular has provided three things Input , Output and Event emitters.

Input helps us define the input data to the user control. Output uses event emitters to send data to the UI in which the user control is located.

Planning how the component will look like

First let us plan how our grid component will look like. Grid component will be called in main HTML using “<grid-ui></grid-ui>” HTML element. The grid component will have three attributes: -

  • grid-columns:- This will be a input in which we will specify the columns names of the grid.
  • grid-data :- This will be again a input in which we will provide the data to be displayed on the grid.
  • grid-selected :- This will be a output from which the selected object will be sent via emitter events to the contained UI.
<grid-ui  [grid-columns]="In this we will give column names"

    [grid-data]="In this we will give data for grid"

    (grid-selected)="The selected object will be sent in event">
</grid-ui>

Step 1 :- Import input , output and Event Emitter

So first let us go ahead and add a separate file for grid component code and name it “GridComponent.ts”.

In this file, we will write all code that we need for Grid component.

The first step is to add necessary components which will bring in Input and Output capabilities. For that we need to import component , Input , Output and event emitter component from “angular/core”.

import {Component,
        Input,
        Output,
        EventEmitter} from "@angular/core"

Step 2 :- Creating the reusable GridComponent class

As this is a component we need to decorate the class with “@Component” decorator. The UI for this component will coded in “Grid.html”. You can also see in the below code we defined the selector has “grid-ui” , can you guess why ?.

If you remember in the planning phase we had said that the grid can be called by using “<grid-ui>” tag.

@Component({
    selector: "grid-ui",
    templateUrl : "../UI/Grid.html"
})
export class GridComponent {
}

Step 3 :- Defining inputs and output

As this is a grid component we need data for the grid and column names for the grid. So we have created two array collection one, “gridColumns” (which will have column names) and “gridData” ( to data for the table).

export class GridComponent {
    // This will have columns
    gridColumns: Array<Object> = new Array<Object>();
    // This will have data
    gridData: Array<Object> = new Array<Object>();
}

There are two methods “setGridColumns” and “setGridDataSet” which will help us to set column names and table data to the above defined two variables.

These methods will be decorated by using “@Input” decorators and in this we will put the names by which these inputs will be invoked while invoking this component.

// The top decorator and import code is removed
// for clarity purpose

export class GridComponent {
// code removed for clarity
    @Input("grid-columns")
    set setgridColumns(_gridColumns: Array<Object>) {
            this.gridColumns = _gridColumns;
        }
    @Input("grid-data")
    set setgridDataSet(_gridData: Array<Object>) {
            this.gridData = _gridData;
        }
}

The names defined in the input decorator will be used as shown below while making call to the component in the main UI.

<grid-ui  [grid-columns]="In this we will give column names"

    [grid-data]="In this we will give data for grid" >
</grid-ui>

Step 4 :- Defining Event emitters

As discussed in this Labs theory section we will have inputs and outputs. Outputs are again defined by using “@Output” decorator and data is sent via event emitter object.

To define output we need to use “@Output” decorator as shown in the below code. This decorator is defined over “EventEmitter” object type. You can see that the type is “Object” and not “Customer” or “Supplier” because we want it to be of a generic type. So that we can attach this output with any component type.

@Output("grid-selected")
    selected: EventEmitter<Object> = new EventEmitter<Object>();

Now when any end user selects a object from the grid we need to raise event by using the “EventEmitter” object by calling the “emit” method as shown below.

// Other codes have been removed for clarity purpose.
export class GridComponent {
    @Output("grid-selected")
    selected: EventEmitter<Object> = new EventEmitter<Object>();

    Select(_selected: Object) {
        this.selected.emit(_selected);
    }
}

Below goes the full code of “GridComponent.ts” which we have discussed till now.

import {Component,
        Input,
        Output,
        EventEmitter} from "@angular/core"

@Component({
    selector: "grid-ui",
    templateUrl : "../UI/Grid.html"
})
export class GridComponent {
    gridColumns: Array<Object> = new Array<Object>();
    // inputs
    gridData: Array<Object> = new Array<Object>();

    @Output("grid-selected")
    selected: EventEmitter<Object> = new EventEmitter<Object>();
    @Input("grid-columns")
    set setgridColumns(_gridColumns: Array<Object>) {
            this.gridColumns = _gridColumns;
        }

    @Input("grid-data")
    set setgridDataSet(_gridData: Array<Object>) {
            this.gridData = _gridData;
        }
   
    Select(_selected: Object) {
        this.selected.emit(_selected);
    }
}

Step 5 :- Creating UI for the reusable component

Also we need to create UI for the “GridComponent.ts”. Remember if we have an Angular component we NEED A HTML UI for it.

So in the UI folder we will add “Grid.html” in which we will write the code of table display.

In the “GridComponent.ts” ( refer Step 4 of this Lab) we have defined input “gridColumns” variable in which we will provide the columns for the grid. So for that we had made a loop using “*ngFor” which will create the columns “<td>” dynamically.

<table>   
 <tr>
        <td *ngFor="let col of gridColumns">
            {{col.colName}}
        </td>
    </tr>
</table>

And to display data in the grid we need to loop through “gridData” variable.

    {{colObj[col.colName]}}

<a>Select</a>

So the complete code of “Grid.html” looks as shown below.

<table>
    <tr>
        <td *ngFor="let col of gridColumns">
            {{col.colName}}
        </td>
    </tr>
    <tr *ngFor="let colObj of gridData">
        <td *ngFor="let col of gridColumns">
            {{colObj[col.colName]}}
        </td>
        <td><a [routerLink]="['Customer/Add']" (click)="Select(colObj)">Select</a></td>
    </tr>
</table>

Step 6 :- Consuming the component in the customer UI

So now that our reusable component and its UI is completed l, lets call the component in the “Customer.html” UI.

Below is the full proper code which has column names defined in “grid-columns” and in “grid-data” we have set “Customers” collection. This “Customers” collection object is exposed from the “CustomerComponent” class. This “Customers” collection is that collection which we had created during the “HTTP” call lab. This variable has collection of “Customer” data.

<grid-ui

      [grid-columns]="[{'colName':'CustomerCode'},{'colName':'CustomerName'},{'colName':'CustomerAmount'}]"

    [grid-data]="Customers"

    (grid-selected)="Select($event)"></grid-ui>

Also we need to ensure that the old “<table>” code is deleted and is replaced with the above “<grid-ui>” input /output tag.

Step 7 :- Creating events in the main Customer component

If you remember in our "GridComponent" we are emitting event by calling “emit” method. Below is the code snippet for it. Now this event which is emitted needs to caught in the “CustomerComponent” and processed.

export class GridComponent {
    Select(_selected: Object) {
        this.selected.emit(_selected);
    }
}

So in order to catch that event in the main component we need to create a method in “CustomerComponent” file. So in the customer component typescript file we will create a “Select” function in which the selected customer will come from the GridComponent and that selected object will be set to “CurrentCustomer” object.

export class CustomerComponent {
Select(_selected:Customer) {
        this.CurrentCustomer.CustomerAmount =_selected.CustomerAmount;
        this.CurrentCustomer.CustomerCode = _selected.CustomerCode;
        this.CurrentCustomer.CustomerName = _selected.CustomerName;
    }
}

Step 8 :- Defining the component in the mainmodule

Also we need to ensure that the “GridComponent” is loaded in the main module. So in the main module import the “GridComponent” and include the same in the declaration of “NgModule” decorator as shown in the below code.

import { GridComponent }   from '../Component/GridComponent';
@NgModule({
    imports: [RouterModule.forRoot(ApplicationRoutes),
        InMemoryWebApiModule.forRoot(CustomerApiService),
             BrowserModule,ReactiveFormsModule,
             FormsModule,HttpModule],
    declarations: [CustomerComponent,
                MasterPageComponent,
                SupplierComponent,
                WelcomeComponent,
                GridComponent],
    bootstrap: [MasterPageComponent]
})
export class MainModuleLibrary { }

And that’s it hit Control + B , run the server and see your reusable grid working.

Whats in the Next article?

In the next Part 5 section we will look in to How to do dynamic routing and and how to use Jquery in Angular to read Learn Angular part 5 click here.

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

 
GeneralHttp calls Pin
Member 1368036223-Mar-18 3:39
memberMember 1368036223-Mar-18 3:39 
QuestionTimeout Issue in Http post call Pin
Member 1326914128-Jan-18 21:42
memberMember 1326914128-Jan-18 21:42 
SuggestionNo direct link from Part 3 to Part 4 Pin
Member 1279074523-Oct-17 19:02
memberMember 1279074523-Oct-17 19:02 
GeneralRe: No direct link from Part 3 to Part 4 Pin
Shivprasad koirala25-Oct-17 22:02
memberShivprasad koirala25-Oct-17 22:02 
GeneralGreat Tutorial. Pin
Member 1279074523-Oct-17 16:42
memberMember 1279074523-Oct-17 16:42 
QuestionStep 5 :- Creating UI for the reusable component Pin
Member 1024302420-Oct-17 8:38
memberMember 1024302420-Oct-17 8:38 
AnswerRe: Step 5 :- Creating UI for the reusable component Pin
Shivprasad koirala26-Oct-17 4:44
memberShivprasad koirala26-Oct-17 4:44 
QuestionStep 6 :- Creating a simple post and get call Pin
Member 1024302419-Oct-17 20:45
memberMember 1024302419-Oct-17 20:45 
AnswerRe: Step 6 :- Creating a simple post and get call Pin
Shivprasad koirala26-Oct-17 4:43
memberShivprasad koirala26-Oct-17 4:43 
SuggestionStep 2 :- Importing HTTP and WebAPI module in to main module Pin
Ruben Suarez Alvarez18-Oct-17 6:05
memberRuben Suarez Alvarez18-Oct-17 6:05 
GeneralRe: Step 2 :- Importing HTTP and WebAPI module in to main module Pin
Shivprasad koirala26-Oct-17 4:42
memberShivprasad koirala26-Oct-17 4:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web06 | 2.8.190214.1 | Last Updated 22 Sep 2017
Article Copyright 2017 by Shivprasad koirala
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid