使用Router.navigate()后未调用Observable.subscribe()

时间:2018-12-28 18:57:56

标签: angular rxjs angular-router angular-observable

我正在创建一个小应用程序,用于显示数据库中的书籍。 我的项目如下:

| presentational
| ---> book-card
| ---> book-details
| containers
| ---> book-item
| ---> books
| services
| ---> books

我将BookItemComponent用作容器,此类与BooksComponent进行通信。 书籍组件显示书籍卡片(如引导程序样式),书籍卡片组件具有输入(获取书籍信息)和输出(以显示有关书籍的更多操作和详细信息)。 这是这些类的代码:

book-item.component.ts:

export class BookItemComponent implements OnInit {
  book: Book; /*= {"title": "New harry", "author": "J.K Rowling"};*/

  constructor(private booksService: BooksService, private route: ActivatedRoute) { }

  ngOnInit() {
    console.log("BookItemComponent.ngOnInit()");

    this.booksService.getBooks().subscribe(
      (books) => {
        const param = this.route.snapshot.params.id;
        console.log(param);
        this.book = books.find(book => book.id == param);
      });
  }
}


book-item.component.html:

<p>Book-item</p>
<p *ngIf="!book">No book found..</p>
<app-book-details
    [book]="book" 
    (addToFav)="onAddToFav(book)"></app-book-details>

BookItemComponent类与作为主要容器的BooksComponent通信:
books.component.ts

export class BooksComponent implements OnInit {

  books: Book[];

  constructor(private booksService: BooksService, private router: Router) { }

  ngOnInit() {
    this.booksService.getBooks().subscribe(books => {
      this.books = books;
    });
  }

  onShowDetails(event: Book) {
      this.router.navigate(['/', event.id]);
  }
}

最后:
book-card.component.ts:

@Component({
  selector: 'app-book-card',
  templateUrl: './book-card.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  styleUrls: ['./book-card.component.css']
})
export class BookCardComponent {
  @Input() book: Book;
  @Output() showDetails = new EventEmitter<Book>();

  showBookDetails(event: Book) {
    if(event) {
      this.showDetails.emit(event);
    }    
  }
}

**问题**:在BookItemComponent.ngOnInit()方法中,当我使用此方法时:

this.booksService.getBooks().subscribe(
      (books) => {
        const param = this.route.snapshot.params.id;
        this.book = books.find(book => book.id == param);
      });

我可以看到这本书是未定义的,请看这张图片:

enter image description here

1 个答案:

答案 0 :(得分:1)

定影书未定义:

  

**问题**:在BookItemComponent.ngOnInit()方法中,当我使用此方法时:

     

[在此处插入代码块]

     

我可以看到这本书是不确定的...

在您的示例中,直到OnInit才定义书。呈现模板时(在这种情况下,在您可以观察并为book设置值之前),由于尚未定义book,因此会引发错误。

要修复此集public book: Book = {} as Book;,请在TS文件中声明它的位置。

设置public books: Book[] = [];

修复加载错误:

这花了我很多时间,并且作为免责声明,我不是AngularFire的专家,而是在您的books.service.ts中,您在构造函数中定义了books $。但是,这仅被调用过一次。为了让我的书可以加载,我不得不重新定义books $变量。为了简单起见,我添加了一个私有函数,可以在需要时重用它。这是获取书籍和帮助程序功能的样子:

  getBooks(): Observable<Book[]> {
    this.setBooks();
    console.log('BooksService.getBooks() called');
    return this.books$.pipe(catchError((error: any) => Observable.throw(error.json())));
  }

  private setBooks(): void {
    this.books$ = this.booksCollection.snapshotChanges().pipe(
      map(actions => actions.map(action => {
        const data = action.payload.doc.data() as Book;
        const id = action.payload.doc.id;
        return { id, ...data };
      }))
    );
  }