2017-02-16 61 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,以显示版本详细信息部分。
相关问题