使用Angular 2中的服务在组件之间发送数据

时间:2017-02-16 12:03:13

标签: angular angular2-services

我尝试使用服务在两个组件之间发送数据。但是,当孩子出现问题时,我的填充数据会出现问题。组件首次加载。

当您选择'发布'从release-list.component上的无序列表中,它将通过路由器插座加载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]);
    }

}

释放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;
        });
    }

}

3 个答案:

答案 0 :(得分:2)

我认为问题可能是您SubjectReleaseDetailComponent内订阅它之前发布了它的价值。当您第二次执行此操作时,会发布新的Release,并且已创建ReleaseDetailComponent - 这意味着它将起作用。

要解决此问题,您可以尝试在服务中使用BehaviorSubject代替常规SubjectBehaviorSubject将为您提供最新发布的值,即使您在最后一个值发布后订阅它也是如此。它还需要一个默认值,因此您可能希望在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

}

在您的模板中,进行空检查,因为我们设置为BehaviorSubject的默认值为undefined。当然,如果您愿意,可以将默认值(传递到BehaviorSubject的构造函数中的值)设置为空Release或其他内容。

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

如果您想了解有关Subjects的不同类型的更多信息,请参阅以下文档:

我希望这有帮助!

答案 1 :(得分:1)

考虑使用BehaviorSubject作为委托。订阅时BehaviorSubject返回主题的最后一个值,因此postponely加载的组件将始终使用最近的值更新:

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

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

行动中BehaviorSubject的基本示例:Angular 2 Interaction between components using the service

答案 2 :(得分:0)

我认为你在这里混合了两个概念。有两种方法可以做到:

  1. 在发布 - 详细信息组件中,您使用release声明@Input并从发布列表中传递它。您可以随意使用它作为组件中的变量。没有主题,没有订阅。
  2. 您使用上述服务,但您已加载详细信息。就像将它嵌入发布列表html中一样,但*ngIf设置为false,不显示它。当您将所选版本放入主题并开始播放时,您可以将*ngIf设置为true,显示发布详细信息部分。