Saturday, November 12, 2016

Consuming a RESful API with Angular 2 using angular-cli

Angular-cli is a command line interface used to scaffold and build angular2 apps using nodejs style (commonJs) modules. In this tutorial I will build a simple Angular 2 application that consumes a posts RESful API service located at https://jsonplaceholder.typicode.com/posts. This API service belongs to a handful APIs that are available for developers and testers at https://jsonplaceholder.typicode.com/.

Here’s a sample of what you will see if you point your browser to https://jsonplaceholder.typicode.com/posts:

image

The Post object looks like this:
{
  "userId": "number",
  "id": "number",
  "title": "string",
  "body": "string"
}
To continue with this tutorial, you will need to install node.js on your computer, If you do not already have it installed then download and install it from https://nodejs.org.

Once you have installed node.js, then go to a command prompt (or terminal window) and run the following command to globally install angular-cli:

npm install -g angular-cli

This may take some time so be patient. Although you can ignore warnings, if you get any red error messages then try the following:
  • run your command prompt in admin mode. If you are using linux or mac then use sudo
  • otherwise, try to upgrade to the latest version of node.js on tour computer.
Upon successful installation of angular-cli, you can now go ahead an scaffold an angular2 app that serves as a suitable starting point. Go to a convenient working directory and execute the following command to create an app named ng2-posts:

ng new ng2-posts

This also takes some time so patience is a good asset. Once the scaffolding process is complete, let’s see what it looks like. Change into the newly created ng2-posts directory:

cd ng2-posts

To build the application, run the following command:

ng build

To host the web application under a light-weight web server listening on port 4200, run the following command:
ng serve

Note: The ng serve command also builds the application so the ng build step is rather optional.

You can now view the web page in your browser by going to http://localhost:4200. This is what you will see:

image

Let us have a look at all the files that were generated. Load the contents of the ng2-posts folder into Visual Studio Code, which can be downloaded from http://code.visualstudio.com/. This is what the source code looks like:

image

Tip: You can load the application in Visual Studio Code by simply running the command “code .” from inside the main application directory within a terminal window.

Since we will need a Post class to represent our object, we can use angular-cli to create it for us. Type in the following command in a terminal window while in the main ng2-posts folder:

ng generate class Post

This results in the creation of a TypeScript file src\app\post.ts that has the following content:
export class Post {
}
Replace the content of post.ts with the following code:
export class Post {
  userId: number;
  id: number;
  title: string;
  body: string;
  constructor(obj?: any) {
    this.userId = obj && obj.userId || null;
    this.id = obj && obj.id || null;
    this.title = obj && obj.title || null;
    this.body = obj && obj.body || null;
  }
}
Next, we need to create a service that is responsible for all http requests to the RESTful API. Type in the following command in a terminal window while in the main ng2-posts folder:

ng generate service Post

This results in the creation of two TypeScript files:  src\app\post.service.spec.ts & src\app\post.service.ts.

Note:
  • The convention for naming a service is {service name}.service.ts. This is also applied to naming components as {component name}.component.ts.
  • The post.service.spec.ts is the unit test file.
The generated post.service.ts file looks like this:
import { Injectable } from '@angular/core';
@Injectable()
export class PostService {

  constructor() { }
}
Replace the contents of post.service.ts with the following:
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class PostService {

  constructor(private http: Http) { }
  getAll() {
    return this.http.get('
https://jsonplaceholder.typicode.com/posts')
    .map((res: Response) => res.json());
  }
}
The above class is annotated with @Injectable() so that it can be used in dependency injection. In order for this to be possible, we will need to make it a provider at a higher level component. In this case, we will add it as a provider in the app.component.ts class. Edit app.component.ts and add the following import command in line 2:

import { PostService } from "./post.service";

Add the following to the @Component block:

providers: [PostService]

The AppComponent class then looks like this:
import { Component } from '@angular/core';
import { PostService } from "./post.service"

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [PostService]
})
export class AppComponent {
  title = 'app works!';
}
The next step is to create a Post component that actually uses the service that we created and displays some data in HTML. Create a PostComponent class by running the following command in a terminal window while in the main ng2-posts folder:

ng generate component Post

This results in the creation the following files:
src\app\post\post.component.css
src\app\post\post.component.html
src\app\post\post.component.spec.ts
src\app\post\post.component.ts
Note the following:
  • The component files follow the convention mentioned previously and are placed in a dedicated folder named post.
  • The third file (post.component.spec.ts) is for unit testing purposes.
Open the post.component.html and view its contents:
<p>
  post works!
</p>
Also, look at the contents of post.component.ts:
import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-post',
  templateUrl: './post.component.html',
  styleUrls: ['./post.component.css']
})
export class PostComponent implements OnInit {
  constructor() { }

  ngOnInit() { }
}
The above suggests that if we place the tag <app-post></app-post> in a consuming component class, then it will display “Post works!”. Let us test this out. Open app.component.ts in your editor and add the following import statement in line 3:

import { PostComponent } from "./post/post.component";

The app.component.ts would then look like this:
import { Component } from '@angular/core';
import { PostService } from "./post.service";
import { PostComponent } from "./post/post.component";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [PostService]
})
export class AppComponent {
  title = 'app works!';
}
Now let us add the <app-post></app-post> markup inside app.component.html so it looks like this:
<h1>
  {{title}}
</h1>
<app-post></app-post>
Have a peek at the web page. It should look like this:

image

What we just proved is that a custom component can be easily used by another component. Let us now enhance PostComponent so that it displays posts with real remote data coming from a RESTful service. Open post.component.ts in your editor and replace its contents with the following code:
import { Component, OnInit } from '@angular/core';
import {Post} from '../post';
import {PostService} from '../post.service';

@Component({
  selector: 'app-post',
  templateUrl: './post.component.html',
  styleUrls: ['./post.component.css']
})
export class PostComponent implements OnInit {
  results: Array<Post>;

  constructor(private postService: PostService) { }
  ngOnInit() {
    this.postService.getAll().subscribe(
      data => { this.results = data; },
      error => console.log(error)
    );
  }
}
Note the following about the above code:
  • Both Post class and PostService must first get imported.
  • PostService is being injected into the constructor making its instance available to the rest of the class. This is possible because of dependency injection and the fact that we previously added it as a provider inside app.component.ts.
  • The ngOnInit() method runs after the class is initialized. It calls the service’s getAll() method and hydrates the results array of Post objects with actual data coming from the RESTful API service.
The last step is to render data into our HTML view. Open post.component.html and replace its content with the following:
<table *ngIf="results" border="1">
  <thead>
    <tr>
      <th>User ID</th>
      <th>ID</th>
      <th>Title</th>
      <th>Body</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let p of results; let i=index">
      <td>{{p.userId}}</td>
      <td>{{p.id}}</td>
      <td>{{p.title}}</td>
      <td>{{p.body}}</td>
    </tr>
  </tbody>
</table>
The hour of truth is at hand. View the web page in your browser. It should resemble this:

image

This should be a great starting point for you to appreciate Angular 2 and do more interesting things with it.

References:

https://dzone.com/articles/getting-started-and-testing-with-angular-cli-and-angular-2-rc5-part-1
https://www.sitepoint.com/angular-2-tutorial/
http://www.mithunvp.com/build-angular-apps-using-angular-2-cli/

No comments:

Post a Comment