将值从服务传递到组件

时间:2018-02-25 16:51:11

标签: angular typescript angular5

我遇到了一个真正的问题,即将一个变量从服务(LibraryService)传递到一个在目录结构中更深层次的组件(ReadingPaneComponent)。这是在我赢得一场激烈的战斗之后,从一个更深层次的组件(AuthorsComponent)将此变量引入服务。因此,有效地,ReadingPaneComponent是AuthorsComponent的“阿姨/叔叔”,因此我尝试通过现有的LibraryService发送变量,该服务还用于从我的后端数据库中提取数据。

我要做的就是将最多五位数字传递给ReadingPaneComponent,这些数字代表一本书的ID。服务完全可以很好地检测出这个数字,但我不能因为爱而没有金钱将它作为“未定义”之外的其他内容传入ReadingPaneComponent。当用户点击书名时,我也调用了AuthorsComponent在ReadingPaneComponent中定义的方法,因此这可能是异步调用的问题,或者是ReadingPaneComponent中的方法应该处于什么生命周期钩子中(当前ngOnInit但我认识到这一点)可能是错的,并尝试了无可比拟的替代方案。)

这是来自 library.service.ts 的相关代码: -

import { Injectable, Component, Input } from '@angular/core';
import { HttpClient, HttpResponse, HttpHeaders } from '@angular/common/http';
import { Language } from '../shared/language.model';
import { Author } from '../shared/author.model';
import { Book } from '../shared/book.model';
import { environment } from '../../environments/environment';
import { Observable } from 'rxjs/observable';
import { Subject } from 'rxjs/Subject';
import { AngularFireModule } from 'angularfire2';
import { AngularFireDatabaseModule } from 'angularfire2/database';
import {
  AngularFireDatabase,
  AngularFireList,
  AngularFireObject } from 'angularfire2/database';
import { AngularFireAuthModule } from 'angularfire2/auth';

@Injectable()
export class LibraryService {
  private chosenBookSource = new Subject<number>();
  chosenBook$ = this.chosenBookSource.asObservable();

// MORE CODE HERE

chosenBook(data) {
    console.log(data); //This shows the correct ID of the book clicked by the user, so I know this is working properly.
    this.chosenBookSource.next(data);
    return data;
  }

这是来自 reading-pane.component.ts : -

import { Component, OnInit, Input, OnDestroy } from '@angular/core';
import { LibraryService } from '../library.service';
import { Language } from '../../shared/language.model';
import { Author } from '../../shared/author.model';
import { Book } from '../../shared/book.model';
import { Observable } from 'rxjs/observable';

@Component({
  selector: 'app-reading-pane',
  templateUrl: './reading-pane.component.html',
  styleUrls: ['./reading-pane.component.css'],
  providers: [LibraryService]
})
export class ReadingPaneComponent implements OnInit, OnDestroy {
  @Input() bookPGID: number;
  public bookHTML;

  constructor(private libraryService: LibraryService) {
  }

  ngOnInit() {
    console.log(this.libraryService.chosenBook$);
    this.libraryService.chosenBook$.subscribe(data => (this.bookPGID = data));
    console.log(this.bookPGID);
    this.libraryService
      .loadBook(this.bookPGID)
      .subscribe((book: Observable<any>) => (this.bookHTML = book));
  }

AuthorsComponent中的调用有效,因为它确实触发了ReadingPaneComponent中的loadBook函数,只是ID号在从LibraryService到ReadingPaneComponent的旅程中无法存活。

感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

看起来问题在于声明了LibraryService。

如果ReadingPaneComponent内部使用了AuthorsComponent,例如:

<!-- AuthorsComponent.html -->
<h1>Authors</h1>
...
<reading-pane-component></reading-pane-component>

然后尝试从阅读窗格的providers: [LibraryService]装饰器中删除@component。该声明是为阅读窗格组件的每个实例创建一个新的LibraryService实例。如果从阅读窗格中删除该声明,它将从其父级继承LibraryService,即authors组件。

如果您的阅读窗格未在作者内部使用,请尝试在您的应用程序模块中声明LibraryService提供程序。从作者和阅读窗格组件中删除providers: [LibraryService]。然后将其添加到您应用的@NgModule装饰器。

Have a look at this plnkr,您会看到:

  1. src/app.ts中声明的LibraryServiceOnce。在整个应用程序中,它产生的值是相同的
  2. src/AuthorsComponent.ts中声明的LibraryService。它为作者组件的每个实例生成不同的值
  3. 嵌套在作者中的读取窗格组件,未声明任何LibraryService提供程序。它取而代之的是其父作者组件的值。
  4. 希望有所帮助!