Communicating with the Server Using HTTP, Observables, and Rx Check code at: https://github.com/wghglory/angular2-fundamental 
Observable features 
Can be Synchronous and Async 
Impoved Error Handling 
Can be closed independently of returning a value 
Can deal with Time 
Advanced Operations
Mathmetical Aggregation 
Buffering 
Debounce 
Distinct 
Filtering 
Combining Observables 
Retry 
 
 
 
Observables VS Promise Promise:
represent a single value in the future 
Async 
 
Observables:
represent 0 or more values now or in the future 
both sync and async 
 
HttpModule app.module.ts
1 2 3 4 5 6 7 8 9 10 + import  {HttpModule} from  '@angular/http'  @NgModule({     imports: [         BrowserModule,         RouterModule.forRoot(appRoutes),         FormsModule,         ReactiveFormsModule, +        HttpModule     ]}) 
 
EventService Http 
note: normally, http return Observable, there must be somewhere call subscribe() to return real data. If we don’t need response data, probably call subscribe() immediately after the http. Otherwise, call subscribe() when you call the service Exception: when using resolver, subscribe is not needed (Eventlist and event-detail)
 
event.service.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 import  { Injectable, EventEmitter } from  '@angular/core' import  { Subject, Observable } from  'rxjs/RX' import  { IEvent, ISession } from  './event.model' import  { Http, Response, Headers, RequestOptions } from  '@angular/http' @Injectable() export  class  EventService   {    constructor (private http: Http) { }     getEvents(): Observable<IEvent[]> {         return  this .http.get('/api/events' ).map((res: Response ) =>  {             return  <IEvent[] > res.json();         }).catch(this.handleError);     }     getEvent(id: number): Observable<IEvent> {         return this.http.get('/api/events/' + id).map((res: Response) => {             return <IEvent>res.json();         }).catch(this.handleError);     }     saveEvent(event): Observable<IEvent> {         let headers = new Headers({ 'Content-Type': 'applicaton/json' });         let options = new RequestOptions({ headers: headers });         //put is exactly same code with post         return this.http.post('/api/events', JSON.stringify(event), options)             .map((res: Response) => {                 console.log(res)                 return res.json();             }).catch(this.handleError);     }     // move this to saveEvent, if id passes => update, no id => add     // updateEvent(event) {     //     let index = EVENTS.findIndex(x => x.id == event.id)     //     EVENTS[index] = event     // }     searchSessions(searchTerm: string) {         return this.http.get('/api/sessions/search?search=' + searchTerm).map((res: Response) => {             return res.json();         }).catch(this.handleError);     }     private handleError(err: Response) {         return Observable.throw(err.statusText);     } } 
 
event-list-resolver.service.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 import  {Injectable} from  '@angular/core' import  {Resolve} from  '@angular/router' import  {EventService} from  './shared/event.service' @Injectable() export  class  EventListResolver  implements  Resolve <any > {    constructor (private eventService: EventService) {    }     resolve() {                  return  this .eventService.getEvents();     } } 
 
create events/event-resolver.service.ts
1 2 3 4 5 6 7 8 9 10 11 12 import  {Injectable} from  '@angular/core' import  {Resolve, ActivatedRouteSnapshot} from  '@angular/router' import  {EventService} from  './shared/event.service' @Injectable() export  class  EventResolver  implements  Resolve <any > {    constructor (private eventService: EventService) {    }     resolve(route: ActivatedRouteSnapshot) {         return  this .eventService.getEvent(+route.params['id' ]);     } } 
 
event-detail.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ngOnInit() {                    this .route.data.forEach((data ) =>  {                                                                                          this .event = data['event' ];         this .addMode = false ;         this .filterBy = 'all' ;         this .sortBy = 'votes' ;     }); } 
 
delete event-route-activator.ts guard since we don’t want to call httprequrest twice, also delete any related code in module, route.
1 2 3 4 5 6 7 8 9 10 11 12 13 export  class  EventRouteActivator  implements  CanActivate   {    constructor (private eventService: EventService, private router: Router) { }     canActivate(route: ActivatedRouteSnapshot) {                  const  eventExists = !!this .eventService.getEvent(+route.params['id' ])           if  (!eventExists)             this .router.navigate(['/404' ])         return  eventExists     } } 
 
modify route.ts
1 { path : 'events/:id' , component : EventDetailComponent, resolve : { event : EventResolver } },  
 
create-event.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 export  class  CreateEventComponent   {    isDirty: boolean = true      constructor (private router: Router, private eventService: EventService) { }     cancel() {         this .router.navigate(['/events' ])     }     saveEvent(formValues) { +        this .eventService.saveEvent(formValues).subscribe(e  =>  { +            this .isDirty = false  +            this .router.navigate(['/events' ]) +        });     } } 
 
VoterService Http voter.service.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import  { Injectable } from  '@angular/core' import  { ISession } from  '../shared/event.model' import  {Http, Response, Headers, RequestOptions} from  '@angular/http' import  { Observable } from  'rxjs/Rx' @Injectable() export  class  VoterService   {    constructor (private http: Http) { }     deleteVoter(eventId: number, session : ISession, voterName : string) {         session.voters = session.voters.filter(v  =>  v !== voterName);         let  url = `/api/events/${eventId} /sessions/${session.id} /voters/${voterName} ` ;         return  this .http.delete(url).catch(this .handleError).subscribe();                       }     addVoter(eventId: number, session : ISession, voterName : string) {         session.voters.push(voterName);         let  headers = new  Headers({ 'Content-Type' : 'applicaton/json'  });         let  options = new  RequestOptions({ headers : headers });         let  url = `/api/events/${eventId} /sessions/${session.id} /voters/${voterName} ` ;                  return  this .http.post(url, JSON .stringify({}), options)             .map((res: Response ) =>  {                 return  res.json();             }).catch(this .handleError).subscribe();     }     userHasVoted(session: ISession, voterName : string) {         return  session.voters.some(v  =>  v === voterName);     }     private handleError(err: Response) {         return  Observable.throw(err.statusText);     } } 
 
Login/Logout user/auth.service.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 import  {Injectable} from  '@angular/core' import  {IUser} from  './user.model' + import  {Http, Response, Headers, RequestOptions} from  '@angular/http'  + import  { Observable } from  'rxjs/Rx'  @Injectable() export  class  AuthService   {+    constructor (private http: Http) { }     currentUser: IUser +    loginUser(userName: string, password : string) {         let  headers = new  Headers({ 'Content-Type' : 'applicaton/json'  });         let  options = new  RequestOptions({ headers : headers });         let  loginInfo = { username : userName, password : password };                  return  this .http.post('/api/login' , JSON .stringify(loginInfo), options)             .do((res: Response ) =>  {                 if  (res) {                     this .currentUser = <IUser > res.json().user;                 }             }).catch(err => {                 return Observable.of(false);             });     }     isAuthenticated() {         return !!this.currentUser;     }     updateCurrentUser(firstName: string, lastName: string) { +        this.currentUser.firstName = firstName;         this.currentUser.lastName = lastName;         let headers = new Headers({ 'Content-Type': 'applicaton/json' });         let options = new RequestOptions({ headers: headers });         return this.http.put(`/api/users/${this.currentUser.id}`, JSON.stringify(this.currentUser), options);     }     //persist user authentication status, call this is app.component.ts +    checkAuthenticationStatus() {         return this.http.get('/api/currentIdentity').map((res: any) => {             if (res._body) {                 return res.json()             } else {                 return {}             }         }).do(currentUser => {             if (!!currentUser.userName) {                 this.currentUser = currentUser;             }         }).subscribe();     } +    logout() {         this.currentUser = undefined;         let headers = new Headers({ 'Content-Type': 'applicaton/json' });         let options = new RequestOptions({ headers: headers });         return this.http.post('api/logout', JSON.stringify({}), options);     } } 
 
app.Component.ts: to persist authentication state, a logged in user should not type username/password within 20 min
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import  { Component } from  '@angular/core' import  {AuthService} from  './user/auth.service' @Component({     selector: 'events-app' ,     template: `<nav-bar></nav-bar><router-outlet></router-outlet>`  }) export  class  AppComponent   {    constructor (private auth: AuthService) { }     ngOnInit() {         this .auth.checkAuthenticationStatus();     } } 
 
login.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 export  class  LoginComponent   {    constructor (private authService: AuthService, private router: Router) { } +    loginInvalid: boolean = false ; +    login(formValues) {         this .authService.loginUser(formValues.userName, formValues.password)             .subscribe(res  =>  {                 if  (!res) {                     this .loginInvalid = true ;                 }                 else  {                     this .router.navigate(['events' ]);                 }             })     }     cancel() {         this .router.navigate(['events' ])     } } 
 
profile.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 export  class  ProfileComponent  implements  OnInit   {    constructor (private authService: AuthService, private router: Router, @Inject(TOASTR_TOKEN) private toastr: Toastr) { } +    saveProfile(formValues) { +        if  (this .profileForm.valid) { +            this .authService.updateCurrentUser(formValues.firstName, formValues.lastName) +                .subscribe(()  =>  { +                    this .toastr.success('Profile saved successfully!' ) +                }); +             +        } +    } +    logout(){ +        this .authService.logout().subscribe(() => { +            this .router.navigate(['/user/login' ]); +        }); +    } }