web-dev-qa-db-ja.com

JSONデータをAngular2コンポーネントに読み込む方法

Tinterwebで多くのチュートリアルを実行した後、ようやくAngular2を使用して便利なものを作成しようとし始め、最初の問題に遭遇しました。 JSONデータをサービスコンポーネントにロードできないようです。

私のpeople.jsonファイルは、最上位フォルダーのdataというフォルダーに保存されます。

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" }
]

私の問題は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は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();
    }
} 

これは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])

...そしてここがインデックスページです...

<!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>

どんな助けも大歓迎です;)

7
Beaker

実際、データが非同期にロードされるためです。したがって、コンポーネントのコンストラクター内では、最初は未定義の値を取得します。

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

コンストラクタをそのように保つには、サービスのgetFriendsメソッドがオブザーバブルを返すようにコードをリファクタリングする必要があります。

@Injectable()
export class FriendService { 
  constructor(private http:Http) {
  }

  getFriends() {
    return this.http.request('./data/people.json')
                 .map(res => res.json());
  }
}

次に、asyncパイプをコンポーネントテンプレートに使用できます。

template: `
    <h1>Hello from the {{ componentName }}!</h1>
    <div *ngFor="#f of friends | async">
        <h3>Name: {{ f.name }}</h3> 
        <h4>Age: {{ f.age }}</h4> 
    </div>
`
14