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

Angular 使用Router.navigate()后未调用Observable.subscribe(),angular,rxjs,angular-router,angular-observable,Angular,Rxjs,Angular Router,Angular Observable,我正在创建一个显示数据库中书籍的小应用程序。 我的项目如下所示: | presentational | ---> book-card | ---> book-details | containers | ---> book-item | ---> books | services | ---> books 我使用BookItemComponent作为容器,这个类与BookItemComponent通信。 Books组件显示bookstrap样式的图书卡,books

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

| presentational
| ---> book-card
| ---> book-details
| containers
| ---> book-item
| ---> books
| services
| ---> books
我使用BookItemComponent作为容器,这个类与BookItemComponent通信。 Books组件显示bookstrap样式的图书卡,bookstrap组件有输入(获取图书信息)和输出(显示图书的更多操作和细节)。 以下是这些类的代码:

book-item.component.ts:


book-item.component.html:

最后:
book-card.component.ts:

我看到那本书没有定义,看这张图片:


未定义修复书:

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

[在此插入代码块]

我可以看出那本书没有定义

在您的示例中,直到OnInit才定义book。当呈现模板时(在本例中,在您的observable和设置book的值之前),它会抛出错误,因为book尚未定义

将此集合
publicbook:book={}修复为book在TS文件中声明它的位置

设置
公共图书:Book[]=[]

修复加载错误:

这花了我相当长的时间,作为免责声明,我不是AngularFire方面的专家,但在您的books.service.ts中,您在构造函数中定义books$。然而,这只被称为一次。为了让我加载您的书籍,我必须重新定义books$变量。为了方便起见,我添加了一个私有函数,您可以在需要时重用它。下面是get books和helper函数的外观:

  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 };
      }))
    );
  }
getBooks():可观察{
这个。setBooks();
log('BooksService.getBooks()已调用');
返回这个.books$.pipe(catchError((error:any)=>Observable.throw(error.json()));
}
私有setBooks():void{
this.books$=this.booksCollection.snapshotChanges().pipe(
map(actions=>actions.map(action=>{
const data=action.payload.doc.data()作为Book;
const id=action.payload.doc.id;
返回{id,…data};
}))
);
}

您好,您订阅的
图书是否未定义(console.log有什么功能)?欢迎使用stack overflow!第一步是找出哪些源值是未定义的。如上所述,
书籍
是否未定义?
param
是否未定义?您的
书籍
是否有
id
属性?(book-item.component.ts中显示的示例似乎不存在?)如果是,属性是否为数字?请注意,参数id将是一个字符串,因此除非将其强制为数字,否则它们不会匹配。您好,谢谢您的回复。如果我初始化
书籍
书籍
就不会再有错误了,很好,但是我仍然没有加载书籍,没有找到任何人。我注意到,如果我刷新页面,将加载书籍详细信息。您可以查看我的代码(我编辑了我的帖子),这样当您第一次加载页面时,您不会看到任何书籍,但当您刷新页面时,您会看到它们?没错。当我在主页上时,我选择一本书:。但找不到任何书籍:。如果我刷新此页面,将加载书籍详细信息@我更新了我的答案以帮助您解决重新加载问题。我看了您的回复,这似乎是一个很好的解决方案!我还没有测试,但我会很快告诉你结果。谢谢。
<p>Book-item</p>
<p *ngIf="!book">No book found..</p>
<app-book-details
    [book]="book" 
    (addToFav)="onAddToFav(book)"></app-book-details>
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]);
  }
}
@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);
    }    
  }
}
this.booksService.getBooks().subscribe(
      (books) => {
        const param = this.route.snapshot.params.id;
        this.book = books.find(book => book.id == param);
      });
  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 };
      }))
    );
  }