2017-02-16 64 views
2

我試圖使用服務在兩個組件之間發送數據。但是,我在第一次加載'child'組件時遇到數據填充問題。使用Angular 2中的服務在組件之間發送數據

當您從release-list.component上的無序列表中選擇'release'時,它將通過router-outlet加載release-detail.component。 release-detail.component應該顯示發佈者。

如果您選擇一個版本,然後再次選擇一個版本,它會起作用。但是在填充數據之前,我必須兩次「加載」release-detail.component。我覺得我很接近,但我必須錯過一些東西。任何幫助將不勝感激。

感謝

我已經提到既是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

我想問題可能是你的Subject發佈它的價值你訂閱它的ReleaseDetailComponent內部之前。當您第二次執行此操作時,會發佈一個新的Release,並且已經創建了ReleaseDetailComponent - 這意味着它將起作用。

要解決此問題,您可以嘗試在服務中使用BehaviorSubject而不是常規的Subject。即使您在發佈最後一個值後訂閱了它,BehaviorSubject也會爲您提供最新發布的值。它也期望一個默認值,所以你可能想在你的ReleaseDetailComponent模板中添加一些空值檢查。

實現可能是這個樣子:

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空檢查,爲默認值,我們設置爲BehaviorSubjectundefined。當然,如果您願意,您可以將默認值(傳遞給BehaviorSubject的構造函數的值)設置爲空的Release或其他東西。

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

這裏是文檔,如果你想了解更多有關不同類型的Subjects

我希望這有助於!

+0

輝煌。謝謝,Fredrik! 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 
} 

基本例如:Angular 2 Interaction between components using the service

+0

謝謝,Seidme。你和弗雷德裏克都是關鍵人物。非常感激! – bmd

+0

不客氣,很高興它幫助^^。 –

+0

完成。謝謝,Seidme – bmd

0

我認爲你是混合這裏有兩個概念。有兩種方法可以做到這一點:

  1. 在釋放細節分量聲明的release@Input並從釋放名單通過。你可以隨意使用它作爲組件中的變量。沒有主題,沒有訂閱。
  2. 您使用上述服務,但您已經加載了詳細信息。就像將它嵌入到發佈列表html中,但是*ngIf設置爲false,不會顯示它。當您將所選版本放入主題中時,它會啓動,然後您可以將*ngIf設置爲true,以顯示版本詳細信息部分。
相關問題