Connecting to the Server
A Simple RESTful API
Building RESTful API is beyond scope of angular since its server side technology like node, ruby on rails etc. But as an angular developer, need to know how to connect to RESTful API. Will connect to a fake RESTful api
https://jsonplaceholder.typicode.com/
or Google jsonplaceholder
Learn how to communicate with server in your angular apps
.e.g
https://jsonplaceholder.typicode.com/posts
Getting Data from the Server
Will use http class in angular. Use it to make ajax calls to server.
get()
post()
put() // for update
patch() //for update
delete()
head() // get meta data about resource. Used to get existence of resource
Should make http calls in Service.
Create new file post.service.ts
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';
export class PostService{
constructor(private _http: Http){
}
getPost(){
return this._http.get("https://jsonplaceholder.typicode.com/posts")
.map(res => res.json())
}
}
Sending Data to the Server
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';
export class PostService{
private _url = "https://jsonplaceholder.typicode.com/posts";
constructor(private _http: Http){
}
getPosts(){
return this._http.get(this._url)
.map(res => res.json())
}
createPost(post){
this._http.post(this._url,JSON.stringify(post))
.map(res => res.json());
}
}
Dependency Injection
Our service is ready. Now need to inject it into our component. First need to mark this class as available for dependency injection.
In post.service.ts, add
import {Injectable} from '@angular/core';
@Injectable()
app.component.ts
import {Component} from '@angular/core';
import {PostService} from './post.service';
import {HTTP_PROVIDERS} from '@angular/http';
@Component({
moduleId: module.id,
selector: 'app-root',
template: `
`,
providers:[PostService, HTTP_PROVIDERS]
})
export class AppComponent {
constructor(private _postService: PostService){
this._postService.getPosts()
.subscribe(posts => console.log(posts));
}
}
Component's Lifecycle Hooks
Even though our code works, doesn't follow the best practises. COnstructor should not contain costly operations.
Components have a lifecycle hooks that we can tap into during the key moments of a component's lifecycle.
OnInit
OnDestroy
DoCheck
OnChanges
AfterContentInit
AfterContentChecked
AfterViewInit
AfterViewChecked
We need to implement one for more interfaces. Each interface has a method that we need to add to our components. When the right moment arrives, Angular will call these methods. For e.g. we can implement the OnInit interface when the component is first instantiated.
import {Component} from '@angular/core';
import {PostService} from './post.service';
import {HTTP_PROVIDERS} from '@angular/http';
import {OnInit} from '@angular/core';
@Component({
moduleId: module.id,
selector: 'app-root',
template: `
`,
providers:[PostService, HTTP_PROVIDERS]
})
export class AppComponent implements OnInit {
constructor(private _postService: PostService){
}
ngOnInit(){
// this method will be called when the component is instantiated. Its called after constructor
// constructor should contain light weight operations. IF need to connect to server, should do so in ngOnInit
this._postService.getPosts()
.subscribe(posts => console.log(posts));
}
}
To implement more than one interface
export class AppComponent implements OnInit, OnDestroy {
Static Type Checking
Create Post interface
export interface Post{
// what fields do we need here?
userId: number;
id?: number;
title: string;
body: string;
}
post.service.ts
import {Http} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import {Injectable} from '@angular/core';
import {Post} from './post';
@Injectable()
export class PostService{
private _url = "https://jsonplaceholder.typicode.com/posts";
constructor(private _http: Http){
}
getPosts() : Observable<Post[]>{
return this._http.get(this._url)
.map(res => res.json())
}
createPost(post : Post){
this._http.post(this._url,JSON.stringify(post))
.map(res => res.json());
}
}
app.component.ts
import {Component} from '@angular/core';
import {PostService} from './post.service';
import {HTTP_PROVIDERS} from '@angular/http';
import {OnInit} from '@angular/core';
@Component({
moduleId: module.id,
selector: 'app-root',
template: `
`,
providers:[PostService, HTTP_PROVIDERS]
})
export class AppComponent implements OnInit {
constructor(private _postService: PostService){
this._postService.createPost({userId: 1, title: "a", body: "b"});
}
ngOnInit(){
// this method will be called when the component is instantiated. Its called after constructor
// constructor should contain light weight operations. IF need to connect to server, should do so in ngOnInit
this._postService.getPosts()
.subscribe(posts => console.log(posts[0].userId));
}
}
Showing a Loader Icon
When getting content from server, useful to show a loader icon to user
import {Component} from '@angular/core';
import {PostService} from './post.service';
import {HTTP_PROVIDERS} from '@angular/http';
import {OnInit} from '@angular/core';
@Component({
moduleId: module.id,
selector: 'app-root',
template: `
<div *ngIf="isLoading">Getting data...</div>
`,
providers:[PostService, HTTP_PROVIDERS]
})
export class AppComponent implements OnInit {
isLoading = true;
constructor(private _postService: PostService){
this._postService.createPost({userId: 1, title: "a", body: "b"});
}
ngOnInit(){
this._postService.getPosts()
.subscribe(posts => {
this.isLoading = false;
console.log(posts[0].userId);
});
}
}
Google 'font awesome'
Go to http://fontawesome.io/get-started/
add to index.html in head tag...
template: `
<div *ngIf="isLoading">
<i class="fa fa-spinner fa-spin fa-3x"></i>
</div>
`,
GitHub Example
app.component.ts
import {Component} from '@angular/core';
import {GitHubProfileComponent} from './github-profile.component';
@Component({
moduleId: module.id,
selector: 'app-root',
directives:[GitHubProfileComponent],
template: `
<github-profile></github-profile>
`
})
export class AppComponent {
}
github.service.ts
import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
@Injectable()
export class GitHubService {
private _baseUrl = "https://api.github.com/users/";
constructor(private _http: Http){}
getUser(username){
return this._http.get(this._baseUrl + username)
.map(res => res.json());
}
getFollowers(username){
return this._http.get(this._baseUrl + username + "/followers")
.map(res => res.json());
}
}
github-profile.component.ts
import {Component, OnInit} from '@angular/core';
import {HTTP_PROVIDERS} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/forkJoin';
import {GitHubService} from './github.service';
@Component({
selector: 'github-profile',
styles: [
`
.avatar {
width: 100;
height: 100;
border-radius: 100%;
}
`
],
template: `
<i *ngIf="isLoading" class="fa fa-spinner fa-spin fa-3x"></i>
<h2>@{{ user.login }}</h2>
<img class="avatar" src="{{ user.avatar_url }}">
<h3>Followers</h3>
<div *ngFor="#follower of followers" class="media">
<div class="media-left">
<a href="#">
<img class="media-object avatar" src="{{ follower.avatar_url }}" alt="...">
</a>
</div>
<div class="media-body">
<h4 class="media-heading">{{ follower.login }}</h4>
</div>
</div>
`,
providers: [HTTP_PROVIDERS, GitHubService]
})
export class GitHubProfileComponent implements OnInit {
isLoading = true;
username = "octocat";
user = {};
followers = [];
constructor(private _gitHubService: GitHubService){
}
ngOnInit(){
Observable.forkJoin(
this._gitHubService.getUser(this.username),
this._gitHubService.getFollowers(this.username)
)
.subscribe(
res => {
this.user = res[0];
this.followers = res[1];
},
null,
() => { this.isLoading = false; })
}
}
No comments:
Post a Comment