2017-02-16 46 views
2

サービスを使用して2つのコンポーネント間でデータを送信しようとしています。しかし、「子」コンポーネントが最初に読み込まれたときに、データの読み込みに問題があります。角度2のサービスを使用してコンポーネント間でデータを送信

release-list.componentの順序付けられていないリストから「リリース」を選択すると、release-detail.componentがルータコンセント経由でロードされます。 release-detail.componentには、リリースアーティストが表示されます。

リリースを選択してからもう一度リリースを選択すると機能します。しかし、データが入力される前にrelease-detail.componentを2回 'ロード'する必要があります。私は近くにいると感じるが、私は何かを欠いているに違いない。どんな助けでも大歓迎です。私はprevious questionAngular documentation

release.service.ts

import { Injectable } from '@angular/core'; 
import { Subject } from 'rxjs/Subject'; 

import { MockReleaseList, ReleaseInterface } from './mock-releases'; 

@Injectable() 

export class ReleaseService { 
    private releaseSubject$ = new Subject(); 

    getReleases(): ReleaseInterface[] { 
     return MockReleaseList; 
    } 

    getRelease() { 
     return this.releaseSubject$; 
    } 

    updateRelease(release: {artist: string, title: string, category: string}[]) { 
     // console.log(release); 
     this.releaseSubject$.next(release); 
    } 

} 

リリース-list.component.ts

import { Component, OnInit } from '@angular/core'; 

import { Router } from '@angular/router'; 
import { Location } from '@angular/common'; 

import { ReleaseService } from '../../../shared/services/release.service'; 
import { MockReleaseList, ReleaseInterface } from '../../../shared/services/mock-releases'; 

@Component({ 
    selector: 'ostgut-releases', 
    template: ` 
    <h3>Label List</h3> 
    <ul> 
     <li *ngFor="let release of releases" (click)="onSelect(release)">{{ release.artist }}</li> 
    </ul> 
    <router-outlet></router-outlet> 
    `, 
}) 
export class ReleaseListComponent implements OnInit { 
    private releases: ReleaseInterface[]; 

    constructor (
     private _router: Router, 
     private _releaseService: ReleaseService 
    ) {} 

    ngOnInit(): ReleaseInterface[] { 
     return this.releases = this._releaseService.getReleases(); 
    } 

    onSelect(release: any): void { 
     this._releaseService.updateRelease(release); 
     this._router.navigate(['/release-list/release-detail', release.category]); 
    } 

} 

の両方に言及しました

おかげ

release-detail.component.ts

import { Component, OnInit, Input } from '@angular/core'; 

import { Router, ActivatedRoute, Params } from '@angular/router'; 

import { ReleaseService } from '../../../../shared/services/release.service'; 
import { ReleaseInterface } from '../../../../shared/services/mock-releases'; 

@Component({ 
    selector: 'ostgut-release-detail', 
    template: ` 
    <h3>Release Detail</h3> 
    <p>{{ release.artist }}</p> 
    `, 
}) 
export class ReleaseDetailComponent implements OnInit { 
    private routeParam: string; 
    private routeParamSub: any; 
    private release: any; 

    constructor(
     private _activatedRoute: ActivatedRoute, 
     private _router: Router, 
     private _releaseService: ReleaseService 
    ) {} 

    ngOnInit(): void { 
     this.release = this._releaseService.getRelease().subscribe(release=>{ 
      return this.release = release; 
     }); 
    } 

} 

答えて

2

私はこの問題は、あなたがあなたのReleaseDetailComponent内のそれに加入する前に、あなたのSubjectがその値を公開することもできると思います。 2回目の操作を行うと、新しいReleaseが公開され、ReleaseDetailComponentが既に作成されていることを意味します。

これを修正するには、通常のSubjectの代わりにBehaviorSubjectを使用することができます。 BehaviorSubjectは、最後の値が発行された後に購読しても、最新の公開値を提供します。また、デフォルト値も期待していますので、ReleaseDetailComponentテンプレートにヌルチェックを追加するとよいでしょう。我々はBehaviorSubjectに設定されたデフォルト値がundefinedあるとして、

import { Injectable } from '@angular/core'; 
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; // <-- note the import! 

import { MockReleaseList, ReleaseInterface } from './mock-releases'; 

@Injectable() 

export class ReleaseService { 
    private releaseSubject$ = new BehaviorSubject(undefined); 

    // The rest is the same 

} 

そして、あなたのテンプレートでは、ATTのヌルチェック:

実装は、次のようなものを見ることができます。もちろん、デフォルト値(BehaviorSubjectのコンストラクタに渡された値)を空のReleaseなどに設定することもできます。ここで

template: ` 
    <h3>Release Detail</h3> 
    <p>{{ release?.artist }}</p> <!-- Note the '?' --> 
    `, 

あなたがSubjectsの異なる種類についての詳細を知りたい場合は、ドキュメントです:

私はこれが役に立てば幸い!

+0

ブリリアント。ありがとう、フレドリク! RxJSのコンセプトはまだ私には新しいので、私は少しオフトラックされていただろうという気持ちがありました。私が変更する必要があった唯一の他のものは、ReleaseDetailComponentとngOnInitフックであった - > this.release = this._releaseService.getRelease()。subscribe(release => { return this.release = release; }); – bmd

+0

完了!そしてもう一度ありがとう – bmd

+0

お手伝いを! :) –

2

BehaviorSubjectを代理人として使用することを検討してください。サブスクリプションの際にBehaviorSubjectしたがってpostponelyロードコンポーネントは常に最新の値に更新される、対象の最後の値を返します。アクションでBehaviorSubject

@Injectable 
export class ReleaseService { 
    releaseSource: BehaviorSubject = new BehaviorSubject(null); 

    // No difference when it comes to subscribing to the BehaviorSubject 
} 

Basicの例:Angular 2 Interaction between components using the service

+0

ありがとう、Seidme。あなたとフレドリックの両方がポイントを握っていました。とても有難い! – bmd

+0

よろしくお願いします。うれしいです^^。 –

+0

完了。ありがとう、Seidme – bmd

0

私はあなたが混合していると思います2つの概念がここにあります。あなたは@Inputreleaseを宣言し、リリースリストからそれを渡すリリース・ディテール・コンポーネントで

  1. :それを行うには二つの方法があります。あなたはあなたの自由にそれをコンポーネントの変数として持っています。件名はなく、購読はしていません。
  2. 上記のようにサービスを使用していますが、すでに詳細を読み込んでいます。リリースリストhtmlに埋め込みますが、*ngIfをfalseに設定して表示しません。あなたが選択したリリースをあなたの主題に入れ、それが始動すると、*ngIfをtrueに設定してリリース詳細部分を表示することができます。
関連する問題