【问题标题】:Ionic 5 Firebase Realtime - Favorites in a listIonic 5 Firebase Realtime - 列表中的收藏夹
【发布时间】:2021-04-16 02:20:50
【问题描述】:

我有一个带有摩托车列表的 Ionic 5 应用程序。在那里,用户可以使用切换星形图标来收藏它们。然后,我在包含摩托车数据的用户节点中创建一个寄存器,如下所示:

问题是当摩托车先前被当前用户标记为“收藏”时,我无法在列表中显示“星形”图标(始终显示“星形轮廓”),尽管我可以获得这个来自 Firebase 的数据。

到目前为止,我已经尝试过这种方式,但没有成功(星形图标在所有项目中都保持“星形轮廓”):

list.page.html

<ion-col size="6" *ngFor="let item of motos; let i = index;">
  <ion-card>
    <ion-card-header>
      <ion-fab vertical="top" horizontal="start">
        <ion-fab-button (click)="addToFavorites(item, i)" icon-only color="clear">
          <ion-icon [name]="item.favourited ? 'star' : 'star-outline'"></ion-icon>
        </ion-fab-button>
      </ion-fab>
    </ion-card-header>
    <ion-card-content>
        <div>{{item.fabricante}} {{item.nome}}</div>
        <div>{{item.ano_model}}</div>
    </ion-card-content>
  </ion-card>
</ion-col>

list.page.ts

import { CrudMethodsService } from './services/crud-methods.service';

basePath = 'motos';
basePathU = 'users';

constructor(private crudServices: CrudMethodsService, public afAuth: AngularFireAuth) {      
 this.crudServices.getMotos(this.basePath).subscribe(res => {
    this.motos = res;
    this.afAuth.authState.subscribe(user => {
      if (user){
        this.userId = user.uid;
        const favoritas = 'favoritas';
        this.crudServices.getFavorites(this.basePathU, this.userId, favoritas).subscribe(us => {
          this.isFavorite = us;
          this.isFavorite.forEach(resp => {
            const item = this.motos;
            const p = this.favorites.indexOf(item);
            item.favourited = item.favourited ? false : true;
            for (let j = 0; j < this.motos.length; j++) {
              if (resp.item.key === this.motos[j].key && p === -1) {
                this.favorites.push(item);
                item.favourited = true;
              }
            }
          });
        });
      }
    });
  });
}

crud-methods.service.ts

getMotos(basePath: string) {
  return this.db.list(basePath).snapshotChanges().pipe(map(changes => {
    return changes.map(c => {
      const data = c.payload.val();
      const id = c.payload.key;
      return { key: id, ...(data as object) };
    });
  }));
}

getFavorites(basePath: string, key: string, path: string) {
  return this.db.list(basePath + '/' + key + '/' + path).snapshotChanges().pipe(map(changes => {
    return changes.map(c => {
      const data = c.payload.val();
      const id = c.payload.key;
      return { key: id, ...(data as object) };
    });
  }));
}

【问题讨论】:

  • 请确保您的构造函数中的类型正确。 this.motos 似乎是一组 moto 对象 [{id ...},{id ...}]。在模板中,您使用它来显示所有摩托车。在构造函数中,有两行我不确定您想要实现什么:const item = this.motos; const p = this.favorites.indexOf(item); 为什么要在一系列摩托车中寻找一系列摩托车?
  • @DavidB。这些行只是尝试将第二次获取结果(仅当前用户最喜欢的摩托车)包含到摩托车数组(第一次获取)中。显然这不起作用。

标签: javascript firebase-realtime-database ionic4 angularfire2


【解决方案1】:

您可以使用 rxjs 运算符 switchmap 来实现您的合并行为。 switchmap 允许您使用 Observable 的结果,但使用另一个 Observable 进行响应。因此,您可以像以前那样在没有嵌套订阅的情况下链接 observables(这通常会导致问题)。这在您的构造函数中看起来像这样:

this.motosWithFavoritesObservable = this.afAuth.authState.pipe(
  map(user => user.uid),
  switchMap(userid => {
    return this.crudServices.getFavorites(this.basePathU, userid, 'favoritas');
  }),
  switchMap((favorites: { key: string }[]) => {
    return this.crudServices.getMotos(this.basePath).pipe(
      map((motos: { key: string, favourited: boolean }[]) => {
        favorites.forEach(fav => {
          const index = motos.findIndex(moto => moto.key === fav.key)
          if (index !== -1) { // if the moto corresponding to the fav is found in the list
            motos[index].favourited = true;
          }
        })
      })
    )
  })
);

motosWithFavoritesObservable.subscribe(motos => this.motos = motos);

【讨论】:

  • 我忘记了第二个 switchmap 中的return
  • 这对您有帮助吗?
猜你喜欢
  • 2018-09-04
  • 1970-01-01
  • 2018-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-27
相关资源
最近更新 更多