Working With Read Operation In Angular 2 Applications


As I said previously, I am starting a demo series of CRUD (Create, read, update, and delete) operations in Angular2. This is part two of that series. In case you missed part one, “How to Create RESTful API using Node.js and MySQL", you can read it from here.

In this second part of the tutorial, I am going to cover the following topics:

  • Fetching JSON data from URL
  • Filter pipe
  • Introduction to HTTP module
  • Services
  • Conditionally apply CSS class and more

At the end of the article, you can find the link to the source code on Github. So, feel free to  play with the code yourself.

In Part One, we have already created a table and named it as TASK which has three columns: Id, Title, and Status. Also, we created  Web API. Now, let’s start with fetching the data in Angular2.(Note I am using Angular2 CLI throughout the demo).

Here is the list of a few commands which can be used with Angular-CLI.

Create new component

Command

ng g c "name of the component"

Example

ng g c demo

component

Explanation

Here, ng stands for Angular, g stands for generate, and c stands for component.

Create new component but not the directory (inside the directory )

Command

ng g c "name of the component" –flat

Example

ng g c demo1 –flat

component

–flat will not create new directory

Create component with inline CSS and inline HTML

Command
ng g c "name of the component" –flat -is -it

Example
ng g c demo1 –flat -is -it

component

-is stands for Inline Style
-it stands for Inline template

Deleting Component

Command
 
ng destroy component "name of the component"



Create Service

Command
 
ng g s data

component

Explanation

s stands for service

Create Class

Command

ng g cl "name of class"

Example

ng g cl demo

component

Explanation

cl stands for class

Create custom pipe

Command

ng g p "name of pipe"

Example

ng g p power

component

Explanation

p stands for pipe

Creating data structure/Class
  1. cmd > ng g cl tasks[code language = ”typescript”]  
  2. export class Task {  
  3.     constructor(public Id: String, public Title: String, public Status: String) {}  
  4. }  
  5. [/code]  
So, it will generate one class for us. Now, inside the class, create three properties Id,Title and Status, so that now the object of Task class has 3 properties.

Creating Service

cmd>ng g s taskdata

First, navigate to shared folder, then write the above code to generate service.

What are services?
 
We can say, services mean don’t repeat yourself (Dry)!
 
Now, what does it mean?
 
Let’s say for example, we require one function which can be used by more than one components. Then, what happens is that we just need to write the same code again and again for each component. When we want to change some logic in function, then we need to change it on each and every component.
 
This is why, instead of doing this, we simply create a service in which we can write the code once that can be used by as many components as we want by simply injecting the service Instance. In other languages, services keeps our function and logic centralized.
 
In general, our service can perform the following tasks:
  • Communicate with database.
  • Communicate with components /classes.
  • Some other business logic which is accessible from various places of our application.

 

  1. [code language = ”typescript”]  
  2. public url: string = "https://localhost:3000/Tasks/";  
  3. getAllTasks() {  
  4.         return this._http.get(this.url).map((response: Response) => response.json());  
  5.     }  
  6.     [/code]  
The above function will return all the tasks retrieved from the database.
 
Here, first we need to inject the _http object from @angular/http. Then, we can call out Web API using _http.get method.
 
The Map function can be imported from the rxjs/Rx. It will map the response into JSON format.
  1. [code language = ”typescript”]  
  2. import {  
  3.     Injectable  
  4. } from '@angular/core';  
  5. import {  
  6.     Task  
  7. } from '../tasks/task';  
  8. import {  
  9.     Http,  
  10.     Headers,  
  11.     Response,  
  12.     RequestOptions  
  13. } from '@angular/http';  
  14. import 'rxjs/Rx';  
  15. @Injectable()  
  16. export class TaskdataService {  
  17.     public url: string = "https://rkdemotask.herokuapp.com/Tasks/";  
  18.     constructor(private _http: Http) {}  
  19.     getAllTasks() {  
  20.         return this._http.get(this.url).map((response: Response) => response.json());  
  21.     }  
  22.     deleteTask(item: Task) {  
  23.         let headers = new Headers({  
  24.             'Content-Type''application/json'  
  25.         });  
  26.         let options = new RequestOptions({  
  27.             headers: headers  
  28.         });  
  29.         return this._http.delete(this.url + item.Id, options).map((response: Response) => response.json());  
  30.     }  
  31.     addTask(item: Task) {  
  32.         let body = JSON.stringify(item);  
  33.         let headers = new Headers({  
  34.             'Content-Type''application/json'  
  35.         });  
  36.         let options = new RequestOptions({  
  37.             headers: headers  
  38.         });  
  39.         return this._http.post(this.url, body, options).map((response: Response) => response.json());  
  40.     }  
  41.     getTaskId(id: any) {  
  42.         return this._http.get(this.url + id).map((response: Response) => response.json());  
  43.     }  
  44.     editTask(item: Task) {  
  45.         let body = JSON.stringify(item);  
  46.         let headers = new Headers({  
  47.             'Content-Type''application/json'  
  48.         });  
  49.         let options = new RequestOptions({  
  50.             headers: headers  
  51.         });  
  52.         return this._http.put(this.url + item.Id, body, options).map((response: Response) => response.json());  
  53.     }  
  54. }  
  55. [code]  
The above service contains all methods for create, read, update, and delete. Also, we have imported the Task class here. Http, Headers, Response, RequestOptions can be imported from @angular/http, as shown above.

Note - We need to provide the service inside app.module.ts in order to use it in our application.

 

  1. [code language = ”typescript”]  
  2. import {  
  3.     TaskdataService  
  4. } from './shared/taskdata.service';  
  5. providers: [TaskdataService], [/code]  
Creating Component

So far, we have created class and service. Now, it’s time for component to display the data.

cmd>ng g c tasks

As I am using Angular2-CLI, it will create four files for us.

 

  • tasks.component.css
  • tasks.component.html
  • tasks.component.ts
  • tasks.component.spec.ts

In this article, I am not going to talk about testing, so I removed tasks.component.spec.ts file.

Angular 2 comes with global declaration concept. So, whenever we are creating a component, we need to declare it in app.module.ts, inside the declaration array. But, as we are using Angular-CLI, it will be done automatically by the system, as shown below.

  1. [code language = ”typescript”]  
  2. import {  
  3.     TasksComponent  
  4. } from './tasks/tasks.component';  
  5. @NgModule({  
  6.             declarations: [  
  7.                 AppComponent,  
  8.                 TasksComponent  
  9.             ],  
  10.             [/code]  
Now, the component is divided into two portions - .html and .ts. Let's create .ts first.

Tasks.component.ts

  1. [code language = ”typescript”]  
  2. import {  
  3.     Component,  
  4.     OnInit  
  5. } from '@angular/core';  
  6. import {  
  7.     Task  
  8. } from './task';  
  9. import {  
  10.     TaskdataService  
  11. } from '../shared/taskdata.service';  
  12. import {  
  13.     Router  
  14. } from '@angular/router';  
  15. @Component({  
  16.     selector: 'app-tasks',  
  17.     templateUrl: './tasks.component.html',  
  18.     styleUrls: ['./tasks.component.css']  
  19. })  
  20. export class TasksComponent implements OnInit {  
  21.     allTasks: Task[] = [];  
  22.     constructor(private _datatask: TaskdataService) {}  
  23.     ngOnInit() {  
  24.         this._datatask.getAllTasks().subscribe(  
  25.             (data: Task[]) => {  
  26.                 this.allTasks = data;  
  27.             });  
  28.     }  
  29. }  
  30. [/code].  
TypeScript file can be divide into 3 sections -
  • imports section - contains all the library files used in component. Like task, taskdata.service,etc.

  • component metadata - contains the metadata like selector, templateurl, styleurl and more.

  • class - contains all the logic. 

So, in our example -
  • First, create the array named allTasks which is the type of task.
  • Then, inject the taskdataservice inside the constructor and create the instance of our service.
  • And then finally, call getAllTasks method of our service inside the ngOnInIt event that is a life-cycle hook called by Angular2 for indicating that Angular is done creating the component.

So now, we are good to go for displaying data on our .html. To display the data on HTML, I am using string interpolation method - remember this {{ }}. You can find more about data bindings here.

tasks.component.html

  1. [code language = ”html”] < div class = "container" > < div class = "row" > < div[hidden] = "allTasks.length>0"  
  2. class = "progress" > < div class = "progress-bar progress-bar-striped active"  
  3. role = "progressbar"  
  4. aria - valuenow = "45"  
  5. aria - valuemin = "0"  
  6. aria - valuemax = "100"  
  7. style = "width: 45%" > < span class = "sr-only" > 45 % Complete < /span> < /div> < /div> < div class = "row" > < table class = "table" > < thead > < th > Id < /th> < th > Title < /th> < th > Status < /th> < /thead> < tr * ngFor = "let item of allTasks " > < td > {  
  8.         {  
  9.             item.Id  
  10.         }  
  11.     } < /td> < td > {  
  12.         {  
  13.             item.Title  
  14.         }  
  15.     } < /td> < td > {  
  16.         {  
  17.             item.Status  
  18.         }  
  19.     } < /td> < /tr> < /table> < /div> < /div> [/code]  
Output
component
Now, you all are wondering by seeing the output that the color of status is changing depending on the values ‘done’ and ‘pending’. It is very simple to assign runtime CSS class to any element of HTML, conditionally. So now, let’s see how we can do so.

First, I am creating two CSS classes named as .donestatus and .pendingstatus.
  1. [code language = ”css”].donestatus {  
  2.     color: blue;  
  3. }.pendingstatus {  
  4.     color: red;  
  5. }  
  6. [/code]  
Syntax

[ngClass]="{cssClass: expression}"
 
We can use [ngClass] with property binding, as shown below. It will check if Status=’done’, then apply .donestatus css class; otherwise, it will apply .pendingstatus css class. Isn’t it easy?
  1. [code language = ”html”] < tr * ngFor = "let item of (allTasks |filter:input1.value)" > < td > {  
  2.         {  
  3.             item.Id  
  4.         }  
  5.     } < /td> < td > {  
  6.         {  
  7.             item.Title  
  8.         }  
  9.     } < /td> < td > < span[ngClass] = "{'donestatus': item.Status=='done','pendingstatus': item.Status=='pending'}" > {  
  10.         {  
  11.             item.Status  
  12.         }  
  13.     } < /span></td > < /tr> [/code]  
Creating filter pipe

If you don’t know what pipe is? You don’t need to worry about that, because I had already described what pipes are in my previous article. You can read it here.

cmd>ng g p filter

Note -  To use this pipe anywhere in the application, we must declare the pipe inside app.module.ts, same as what we did with components.

 

  1. [code language = ”typescript”]  
  2. import {  
  3.     FilterPipe  
  4. } from './shared/filter.pipe';  
  5. @NgModule({  
  6.         declarations: [  
  7.             AppComponent,  
  8.             FilterPipe  
  9.         ],  
  10.     })[/code]  
Filter.pipe.ts
  1. [code language = ”typescript”]  
  2. import {  
  3.     Pipe,  
  4.     PipeTransform  
  5. } from '@angular/core';  
  6. @Pipe({  
  7.     name: 'filter'  
  8. })  
  9. export class FilterPipe implements PipeTransform {  
  10.     transform(value: any[], arg: any) {  
  11.         return value.filter(item => item.Title.startsWith(arg));  
  12.     }  
  13. }  
  14. [/code]  
So in the above example, I have created transform function which takes two parameters - array (of type task) and arg ( the search term). I have  performed a simple search filter operation on an array.

So everything is done now. Should we call the filter pipe on our task.component.html?
 
Yes, let’s call it. As I have already declared pipe inside the app.module.ts file, there is no need to import it again on component.

Final task.component.html will look like the following, after applying the filter.

tasks.component.html
  1. [code language = ”html”] < input type = "text" (keyup) = "0"#  
  2. input1 class = "form-control"  
  3. placeholder = "Search for..." > < tr * ngFor = "let item of (allTasks |filter:input1.value)" > [/code][code language=”html”] < div class = "container" > < div class = "row" > < div[hidden] = "allTasks.length>0"  
  4.         class = "progress" > < div class = "progress-bar progress-bar-striped active"  
  5.         role = "progressbar"  
  6.         aria - valuenow = "45"  
  7.         aria - valuemin = "0"  
  8.         aria - valuemax = "100"  
  9.         style = "width: 45%" > < span class = "sr-only" > 45 % Complete < /span> < /div> < /div> < div class = "input-group" > < span class = "input-group-btn" > < button class = "btn btn-default"  
  10.         type = "button" > < span class = "glyphicon glyphicon-search" > < /span></button > < /span> < input type = "text" (keyup) = "0"#  
  11.         input1 class = "form-control"  
  12.         placeholder = "Search for..." > < /div> < /div> < br / > < div class = "row" > < table class = "table" > < thead > < th > Id < /th> < th > Title < /th> < th > Status < /th> < /thead> < tr * ngFor = "let item of (allTasks |filter:input1.value)" > < td > {  
  13.             {  
  14.                 item.Id  
  15.             }  
  16.         } < /td> < td > {  
  17.             {  
  18.                 item.Title  
  19.             }  
  20.         } < /td> < td > < span[ngClass] = "{'donestatus': item.Status=='done','pendingstatus': item.Status=='pending'}" > {  
  21.             {  
  22.                 item.Status  
  23.             }  
  24.         } < /span></td > < /tr> < /table> < /div> < /div> [/code]  
What I did is simply add one input box and created a (keyup) event so that when user inputs data, it filters the below table. I also used template binding.
  1. [code language = ”html”] < input type = "text" (keyup) = "0"#  
  2. input1 class = "form-control"  
  3. placeholder = "Search for..." > < tr * ngFor = "let item of (allTasks |filter:input1.value)" > [/code]  
Filter will take allTasks array as first argument and input1.value as second argument for that transform function inside the filter.pipe.ts.

Output

component
Summary

Angular 2 is simply awesome. Isn’t it?

We covered a lot in this tutorial. Let’s just summarize it.
  • Angular-CLI
  • Created class
  • Services
  • Components
  • Run time css class
  • Filter pipe and more…

There is a lot more to come in the next part of the tutorial (routing, insert, validations, update, and delete). So, stay tuned for more. I will provide the Github link of the demo application in the last part of this tutorial.


Similar Articles