2016-06-28 3 views
0

まずAngular2 Rxjs(およびobservables一般)とES6/ES2015が新しくなりました。問題はこれらのいずれかの結果である可能性があります。Angular2の単一項目rxjsを取得する正しい方法

私は、ストアを作成し、loadAllとload single functionと露出したゲッターの両方を持つサービスを角2で持っています。その私が、コンポーネントで期待どおりのリストを表示することができる午前現在、ダミーデータにフックアップが、最終的にHTTPリクエスト(以下コメントアウト)

import { Injectable } from '@angular/core'; 
import { Observable, Subject } from 'rxjs/Rx'; 
import { Http, Response } from '@angular/http'; 

export interface Article { 
    id: number; 
    title: string; 
    content: string; 
    author: string; 
} 

@Injectable() 
export class ArticleService { 
    private _articles$: Subject<Article[]>; 
    private baseUrl: string; 
    private dataStore: { 
    articles: Article[] 
    }; 

    private dummyData = [ 
     { 
     id: 1, 
     title: 'Title 1', 
     content: 'content 1', 
     author: 'author 1' 
     }, 
     { 
     id:2, 
     title: 'Title 2', 
     content: 'content 2', 
     author: 'author 1' 
     } 
    ]; 

    constructor(private http: Http) { 
    this.baseUrl = 'http://localhost:3000' 
    this.dataStore = { articles: [] }; 
    this._articles$ = <Subject<Article[]>>new Subject(); 
    } 
    get articles$(){ 
    return this._articles$.asObservable(); 
    } 

    loadAll(){ 
    //Observable.fromPromise(Promise.resolve(this.dummyData)) 
    this.http.get(`${this.baseUrl}/articles`) 
     // map for actual http requests 
    .map(response => response.json()) 
    .subscribe(data => { 
     //debugger; 
     this.dataStore.articles = data; 
     // Push a new copy of our article list to all Subscribers. 
     this._articles$.next(this.dataStore.articles) 
    }, error => console.log('Could not load Articles')); 
    } 

    load(id: any) { 
    Observable.fromPromise(Promise.resolve(this.dummyData[id-1])) 
    //this.http.get(`${this.baseUrl}/articles/${id}`) 
     // map for actual http requests 
    //.map(response => response.json()) 
    .subscribe(data => { 
     let notFound = true; 

     this.dataStore.articles.forEach((item, index) => { 
     if (item.id === data.id) { 
      this.dataStore.articles[index] = data; 
      notFound = false; 
     } 
     }); 

     if (notFound) { 
     this.dataStore.articles.push(data); 
     } 

     this._articles$.next(this.dataStore.articles); 
    }, error => console.log('Could not load todo.')); 
    } 
} 

次のようになります。

import { Component, OnInit } from '@angular/core'; 
import { ROUTER_DIRECTIVES } from '@angular/router'; 
import { ArticleService } from '../shared'; 

@Component({ 
    moduleId: module.id, 
    selector: 'app-home', 
    directives :[ 
    ROUTER_DIRECTIVES 
    ], 
    providers:[ 
    ArticleService 
    ], 
    template: ` 
    <h1>My List</h1> 
    <ul> 
     <li *ngFor="let item of items$ | async; let i = index"> 
     <a [routerLink]="['/article', item.id]" > {{item.title}} </a> 
     </li> 
    </ul> 
    `, 
    styleUrls: ['home.component.css'] 
}) 
export class HomeComponent implements OnInit { 
    items$ = null; 
    constructor(private articleService: ArticleService) { 
    this.articleService = articleService; 
    } 

    ngOnInit() { 
    this.items$ = this.articleService.articles$; 
    this.articleService.loadAll(); 
    } 
} 

が、どのようにすることができます私は、これは私が試みているものである、項目コンポーネントに単一の項目を表示:

import { Component, OnInit } from '@angular/core'; 
import { ROUTER_DIRECTIVES, ActivatedRoute, Router } from '@angular/router'; 
import { ArticleService } from '../shared'; 

@Component({ 
    moduleId: module.id, 
    selector: 'app-article', 
    providers: [ 
    ArticleService 
    ], 
    template: ` 
     <h1>{{item$.title}}</h1> 
     <p>{{item$.content}}</p> 
    `, 
    styleUrls: ['article.component.css'] 
}) 
export class ArticleComponent implements OnInit { 
    private sub: any; 
    private id: number; 
    private item$ = null; 
    // private all = null; 

    constructor(private route: ActivatedRoute, 
    private router: Router, private articleService: ArticleService) { 
    this.route = route; 
    this.articleService = articleService; 
    } 

    ngOnInit() { 
    this.sub = this.route.params.subscribe(params => { 
     let id = +params['id']; // (+) converts string 'id' to a number 
     //this.service.getHero(id).then(hero => this.hero = hero); 
     this.id = id 
    }); 

    this.articleService.load(this.id); 
    //this.all = this.articleService.articles$; 
    this.articleService.articles$ 
    .reduce((c, n) => { 
     return n["id"] === this.id ? n : c; 
    }) 
    .subscribe(data => { 
     this.item$ = JSON.stringify(data); 
     }); 
    } 

} 

Iはまた、フィルタリングを試みた:

エラー Argument of type '(n: Article[]) => void' is not assignable to parameter of type '(value: Article[], index: number) => boolean'

と単一項目選択スロー

this.articleService.articles$ 
    .filter((n) => { 
     n["id"] === this.id ; 

     }) 
     .subscribe(data => { 
     this.item$ = data; 
     }); 

:私はthis.item$ = JSON.stringify(data[0])をすれば、ほとんどの混乱のものがある

.subscribe(data => { 
    this.item$ = data[0]; 
}); 

を。文字列化なし{"id":1,"title":"Title 1","content":"content 1","author":"author 1"}[object Object]ように私は{{item$.id}}を参照したり、他の属性が、私はエラーを取得する際に関連している可能性があり、私は気づいたTypeError: Cannot read property 'id' of null

その他の問題は、次のとおりです:私はテンプレートに{{item$}}を参照するときには、通常の文字列として表示されます

私はそれが存在しないため、エラーが発生しますが、0参照 n.id代わりの n["id"]場合
  • 私は(それは難しいけれども、今に再現するために見つけること)occassionsのカップルに
  • を内部デバッガを停止削減やフィルタ機能することはできませんdid
+0

質問は何ですか? – AngJobs

答えて

4

try Elvisオペレータ?.内挿です。場合item$

{{item$?.id}} 

は(等、ヌル、未定義)falsyではidメンバにアクセスしないであろう。

item$は、回答が得られるまでnullになります。

:実際にはfilterと同様の機能の中でデバッガを停止することができます。ちょうどそれを複数行にする。 また、矢印機能が複数行になっているときにconsoleメッセージを入力することもできます。

+0

すごくありがとう – jonnie

関連する問題