Observable.subscribe () не вызывается после использования Router.navigate () - PullRequest
0 голосов
/ 28 декабря 2018

Я создаю небольшое приложение, которое показывает книги из базы данных.Мой проект выглядит так:

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

Я использую BookItemComponent в качестве контейнера, этот класс взаимодействует с BooksComponent.Компоненты books отображают карточку книги (как стиль начальной загрузки), компонент book-card имеет ввод (получить информацию о книге) и вывод (чтобы показать больше действий и подробностей о книге).Вот код для этих классов:

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 голосов
/ 29 декабря 2018

Исправление книги не определено:

** ПРОБЛЕМА **: В методе BookItemComponent.ngOnInit (), когда я использую это:

[вставьте блок кода здесь]

Я вижу, что книга не определена ...

В вашем примере вы не определяете книгу до OnInit.Когда шаблон рендерится (в данном случае перед вашим наблюдаемым и задает значение для книги), он выдает ошибку, потому что книга еще не определена.

Чтобы исправить этот набор public book: Book = {} as Book;, где вы объявляете его в своем файле TS.

И не мешало бы установить public books: Book[] = [];

Исправление ошибки загрузки:

Это заняло у меня довольно много времени и в качестве отказа от ответственностиЯ не эксперт по AngularFire, но в вашем books.service.ts вы определяете books $ в своем конструкторе.Однако это называлось только один раз.Чтобы я мог загрузить ваши книги, мне пришлось переопределить переменную $ books.Чтобы упростить процесс, я добавил приватную функцию, которую вы можете использовать по мере необходимостиВот как выглядят книги get и вспомогательная функция:

  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 };
      }))
    );
  }
...