首页 > 解决方案 > 如何在 Firebase 实时数据库中过滤并在 Angular 应用中显示特定内容?

问题描述

我正在使用 Angular 和 Firebase 实时数据库。我的数据库中有一组名为“imageDetail”的照片,其中每个项目都有:-category - caption - imageUrl

我正在尝试根据它们的类别过滤我的项目,并在单独的组件中显示结果。我设法在控制台中获得了正确的结果,但我的问题是我无法在我的组件中显示结果。

在这个例子中,我试图在我的收藏中过滤“自然”类别,我尝试了很多不同的方法,但我要么得到我收藏中的所有照片,要么根本没有照片。

这是我的图像服务中的功能:

  getImageByCategory(category: string) {

    const dbRef = this.firebaseDB.database.ref('imageDetail');

    return dbRef.orderByChild("category").equalTo(category).on("child_added", snap => {
      console.log(snap.val());  // -> this shows me what I want
    });

  }  

这是我的 Nature 组件,我打算只显示“自然”类别的照片:

import { Component, OnInit } from '@angular/core';
import { ImageService } from '../services/image.service';

@Component({
  selector: 'app-nature',
  templateUrl: './nature.component.html',
  styleUrls: ['./nature.component.css']
})
export class NatureComponent implements OnInit {

  naturePhotos: any[];

  constructor(private imageService: ImageService) {
    this.naturePhotos = [];
  }

  ngOnInit(): void {

    let listaPhoto = this.imageService.getImageByCategory("nature");
    listaPhoto.snapshotChanges().subscribe(
      list => {
        this.naturePhotos = list.map(item => { return item.payload.val() });
      });

  }

}

我还收到此错误消息“类型'(a:DataSnapshot,b?:字符串)=> any'上不存在属性'snapshotChanges'。”

我不太确定出了什么问题,谁能帮我弄清楚如何分离我收藏中的每个类别并让它们显示在几个不同的组件中?

标签: javascriptangularfirebasefirebase-realtime-database

解决方案


方法on(...)不返回结果,它返回您提供的回调 https://firebase.google.com/docs/reference/js/firebase.database.Reference#on

您应该创建一个 Observable 来代替发出您的结果:

getImageByCategory(category: string) {
  const dbRef = this.firebaseDB.database.ref('imageDetail');
  return Observable.create(observer => {
    const callback = dbRef.orderByChild("category")
      .equalTo(category)
      .on('child_added', snap => {
        observer.next(snap.val());
      }, error => observer.error(error));
    // Return a function with teardown logic that run when you unsubscribe
    return () => dbRef.off('child_added', callback);
  });
}  

请注意,我不熟悉 Firebase 数据库,因此这可能不是最好的方法。

在您的组件中,您可以通过多种方式使用它。

使用异步管道(更简单):

@Component({
  selector: 'app-root',
  template: `
<div class="container" *ngFor="let photo of photos$ | async">
  <div class="photo">
    <img src="{{photo.imageURL}}" alt="" />
  </div>
</div>
`
})
export class AppComponent {
  photos$!: Observable<Photo[]>;

  constructor(
    private imageService: ImageService
  ) {}

  ngOnInit(): void {
    this.photos$ = this.imageService.getImageByCategory('nature');
  }
}

通过订阅:

@Component({
  selector: 'app-root',
  template: `
<div class="container" *ngFor="let photo of photos">
  <div class="photo">
    <img src="{{photo.imageURL}}" alt="" />
  </div>
</div>
`
})
export class AppComponent implements OnInit, OnDestroy {
  photos: Photo[] = [];
  private subscription!: Subscription;

  constructor(
    private imageService: ImageService
  ) {}

  ngOnInit(): void {
    this.subscription = this.photos = this.imageService.getImageByCategory('nature')
      .subscribe(photos => this.photos = photos);
      // Or you can do: .subscribe(photos => this.photos.push(...photos);
  }

  ngOnDestroy(): void {
    // This is important to prevent memory leak
    this.subscription.unsubscribe();
  }
}

推荐阅读