3

I have been following the Angular2 example here: https://angular.io/docs/ts/latest/tutorial/

I have got to the end where I have put in place the promise for the mock heroes. I want to go further though and try to put in place a http request to get the heroes list from a 3rd party source.

Say, for example, I have set up a web url http://pastebin.com/raw/2mEEPeUs which returns the list of heroes as json in the format given in the example.

What is the best way to implement this?

From looking at Angular 2, Getting Data Out of Service I thought this might be as easy as updating the following:

hero.service.ts

import {Hero} from './hero';
import {HEROES} from './mock-heroes';
import {Injectable} from 'angular2/core';
import {Http, Response, HTTP_PROVIDERS} from "angular2/http";

@Injectable()
export class HeroService {
constructor(public http: Http){}
  getHeroes(){
    return this.http.request('http://pastebin.com/raw/2mEEPeUs')
        .map(response => response.json());
  }
}

and

app.component.js

ngOnInit() {
  this.getHeroes().subscribe(
    res => this.heroes = res,
    err => this.logError(err));
}
Community
  • 1
  • 1
GrahamJRoy
  • 1,603
  • 5
  • 26
  • 56

2 Answers2

1

In this plunker I created an example with http request: http://plnkr.co/edit/qXwLNh6UHacmHhji80VR

For me there where 3 hard things:

  1. You should add to your index.html
  2. You need to add the HTTP_PROVIDERS to the injector in boot.ts
  3. You need to import rxjs/Rx into the hero service

The code looks like: boot.ts

import {bootstrap} from 'angular2/platform/browser';
import {HTTP_PROVIDERS} from "angular2/http";
import {App} from "./app.component";
import {HeroService} from "./hero.service";

bootstrap(App, [HeroService, HTTP_PROVIDERS]);

Hero-service.ts

import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';
import construct = Reflect.construct;
import 'rxjs/Rx';

@Injectable()
export class HeroService {


    constructor(private _http : Http) {

    }


    public getHeroesAsObservable () {
        // reactive programming
        // https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
        //http://chariotsolutions.com/blog/post/angular2-observables-http-separating-services-components/

        return this._http.get('heroes').map(res => res.json());

    }

}

app.component.ts

import {Component} from 'angular2/core';
import {HeroDetailComponent} from "./hero-detail.component";
import {HeroService} from "./hero.service";
import {OnInit} from "angular2/core";

@Component({
    selector: 'my-app',
    styles:[`
      .heroes {list-style-type: none; margin-left: 1em; padding: 0; width: 10em;}
      .heroes li { cursor: pointer; position: relative; left: 0; transition: all 0.2s ease; }
      .heroes li:hover {color: #369; background-color: #EEE; left: .2em;}
      .heroes .badge {
        font-size: small;
        color: white;
        padding: 0.1em 0.7em;
        background-color: #369;
        line-height: 1em;
        position: relative;
        left: -1px;
        top: -1px;
      }
      .selected { background-color: #EEE; color: #369; }
    `],
    template: `
        <h1>{{title}}</h1>
        <ul class="heroes">
            <li *ngFor="#hero of heroes"
                (click)="onSelectHero(hero)"
                [class.selected]="hero === selectedHero">
                <span class="badge">{{hero.id}}</span> {{hero.name}}
            </li>
        </ul>
        <hero-detail [hero]="selectedHero"></hero-detail>
        `,
    directives:[HeroDetailComponent],
    //providers:[HeroService]
})
export class App implements OnInit{
    public title = 'Tours of Heroes';
    public heroes;
    public selectedHero : Hero;

    constructor(private _heroesService : HeroService) {

    }

    ngOnInit () {
        //this._heroesService.getHeroes().then(heroes => this.heroes = heroes);

        var observable = this._heroesService.getHeroesAsObservable()
            .subscribe(
                data => this.heroes = data,
                err => console.log('ERROR!!!', err)
            );

    }

    onSelectHero (hero : Hero) {
        this.selectedHero = hero;
    }

}

local Index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>tour of heroes tutorial Angular 2</title>


    <!-- 1. Load libraries -->
    <script src="../node_modules/angular2/bundles/angular2-polyfills.js"></script>
    <script src="../node_modules/systemjs/dist/system.src.js"></script>
    <script src="../node_modules/rxjs/bundles/Rx.js"></script>
    <script src="../node_modules/angular2/bundles/angular2.js"></script>
    <script src="../node_modules/angular2/bundles/http.dev.js"></script>

    <!-- 2. Configure SystemJS -->
    <script>
        System.config({
            packages: {
                src: {
                    format: 'register',
                    defaultExtension: 'js'
                }
            }
        });
        System.import('src/boot')
                .then(null, console.error);
    </script>

</head>
<body>
    <my-app>Loading...</my-app>
</body>
</html>


<html>

Adding an async pipe is a good idea! Hope the plunker works for you

Stefan van de Vooren
  • 2,524
  • 22
  • 19
0

You should leverage the async pipe to display the observable in the template. This way you don't have to manage the subscription by your own:

@Component({
  template: `
    <ul>
      <li *ngRepeat="hero of heroes | async">{{hero.name}}</li>
    </ul>
  `
})
export class MyComponent {
  ngOnInit() {
    this.heroes = this.getHeroes();  
  }
}

This answer could also give you some additional hints about the way to implement HTTP requests in services and use them from components:

Hope it helps you, Thierry

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360