How to I load JSON data into Angular2 component

After running through many tutorials on tinterweb I have finally started to try and build something useful to me using Angular2 and I have come across my first issue. I cannot seem to load JSON data into my service component.

my people.json file is stored in a folder called data in the top folder.

people.json

"people":[
    { age: 40, name: "Jordan Houston" },
        { age: 38, name: "Robert Eastham" },
        { age: 23, name: "Josh Beh" },
        { age: 23, name: "Joseph Canina" },
        { age: 24, name: "Alexandra Wilkins" },
        { age: 22, name: "Kiersten Costanzo" },
        { age: 23, name: "Ku Sherwood" },
        { age: 25, name: "Arta Halili" },
        { age: 24, name: "Patrick Cooney" },
        { age: 23, name: "Z.A. Perr" },
        { age: 18, name: "Tyler Mulligan" },
        { age: 26, name: "Dennis Dempsey" },
        { age: 32, name: "Francis Yeager" },
        { age: 23, name: "Phil Belardi" }
]

I believe my issue lies in the friends.service.ts

friend.service.ts

import {Injectable} from 'angular2/core';
import {Http, HTTP_PROVIDERS} from 'angular2/http';

@Injectable()

export class FriendService { 

    friends:Array<any>;

    constructor(private http:Http) 
        {
            //console.log(">>friend.service.ts:constructor--")
            http.request('./data/people.json')
                    .subscribe(response => this.friends = response.json()));
    }

        getFriends()
        {
            //console.log(">>friend.service.ts:getFriends--")
            console.log(this.friends)
            return this.friends
        }   
}

friend.service.ts is used within the friend.component.ts

friend.component.ts

import { Component } from 'angular2/core'; 
import { FriendService } from 'app/friend.service';

@Component({
    selector: 'my-friends',
      providers: [FriendService],
        styles: [`
             div { 
                 background-color:#EFEFEF;
                 margin-bottom:15px;
                 padding:15px;
                 border:1px solid #DDD;
                 box-shadow:2px 2px 2px 0 rgba(0, 0, 0, 0.3);
                border-radius:3px;
            }
        h2 { 
            text-align: center;
        }
    `],
    template: `
        <h1>Hello from the {{ componentName }}!</h1>
        <div *ngFor="#f of friends">
            <h3>Name: {{ f.name }}</h3> 
            <h4>Age: {{ f.age }}</h4> 
        </div>
    `
})


export class FriendComponent {

    componentName: 'FriendComponent';

        constructor(private _friendService: FriendService) 
        {
        this.friends = _friendService.getFriends();
    }
} 

this lives within main.ts

main.ts

import { Component } from 'angular2/core';
import { bootstrap } from 'angular2/platform/browser';

import { FriendComponent } from 'app/friend.component';
import {HTTP_PROVIDERS} from 'angular2/http';


@Component({
  selector: 'my-app',
    directives: [FriendComponent],
  styles: [`
  h1 {
    color:#545454;
    background:#02A8F4;
    padding:15px;
    box-shadow:2px 2px 2px 0 rgba(0, 0, 0, 0.3);
  }
  `]
  template: `
  <div>
  <h1>Hello from the {{componentName}}.</h1>
  <my-friends></my-friends>
  </div>
  `
})
export class AppComponent {
  componentName: 'AppComponent'
}

bootstrap(AppComponent,[HTTP_PROVIDERS])

…and here is the index page…

<!DOCTYPE html>
<html>
<head>
  <script>document.write('<base href="' + document.location + '" />');</script>

  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!--Add Bootstrap CSS Styles-->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">

  <!-- IE required polyfills, in this exact order -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.34.1/es6-shim.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.20/system-polyfills.js"></script>
  <script src="https://npmcdn.com/angular2/es6/dev/src/testing/shims_for_IE.js"></script>

  <!-- Angular polyfill required everywhere -->
  <script src="https://code.angularjs.org/2.0.0-beta.8/angular2-polyfills.js"></script>

  <script src="https://code.angularjs.org/tools/system.js"></script>
  <script src="https://code.angularjs.org/tools/typescript.js"></script>
  <script src="https://code.angularjs.org/2.0.0-beta.8/Rx.js"></script>
  <script src="https://code.angularjs.org/2.0.0-beta.8/angular2.dev.js"></script>
  <script src="https://code.angularjs.org/2.0.0-beta.8/router.dev.js"></script>
  <script src="https://code.angularjs.org/2.0.0-beta.8/http.dev.js"></script>

  <script>
      System.config({
        transpiler: 'typescript', 
        typescriptOptions: { emitDecoratorMetadata: true }, 
        packages: {
          'api': {defaultExtension: 'ts'}, 
          'app': {defaultExtension: 'ts'} 
        } 
      });
    System.import('app/main')
          .then(null, console.error.bind(console));
  </script>

</head>
<body class="container">

  <my-app>Loading...</my-app>

</body>
</html>

Any help would be greatly appreciated 😉

1
Leave a Reply

avatar
1 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
1 Comment authors
Jason Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Jason
Guest

In fact, it’s because your data are loaded asynchronously. So within the constructor of your component, you initially get an undefined value. constructor(private _friendService: FriendService) { this.friends = _friendService.getFriends(); } To keep your constructor like that, you need to refactor your code to make the getFriends method of your service return an observable: @Injectable() export class FriendService { constructor(private http:Http) { } getFriends() { return this.http.request('./data/people.json') .map(res => res.json()); } } Then you can use the async pipe into your component template: template: ` <h1>Hello from the {{ componentName }}!</h1> <div *ngFor="#f of friends | async"> <h3>Name: {{ f.name }}</h3>… Read more »