Ionic 5 Firebase Realtime - 列表中的收藏夹
Ionic 5 Firebase Realtime - Favorites in a list
我有一个带有摩托车列表的 Ionic 5 应用程序。这样,用户可以使用切换星形图标来收藏它们。然后,我在包含摩托车数据的用户节点中创建一个寄存器,如下所示:
问题是当摩托车之前被当前用户标记为“收藏”时,我无法在列表中显示“星号”图标(总是显示“star-outline”),尽管我可以从 Firebase 获取这些数据。
到目前为止我已经尝试过这种方式,但没有成功(星形图标在所有项目中保持“star-outline”):
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) };
});
}));
}
您可以使用 rxjs 运算符 switchmap
来实现您的合并行为。 switchmap
允许您使用一个 Observable 的结果,但用另一个 Observable 响应。因此,您可以像以前一样在没有嵌套订阅的情况下链接可观察对象(这通常会导致问题)。这在您的构造函数中看起来像这样:
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);
我有一个带有摩托车列表的 Ionic 5 应用程序。这样,用户可以使用切换星形图标来收藏它们。然后,我在包含摩托车数据的用户节点中创建一个寄存器,如下所示:
问题是当摩托车之前被当前用户标记为“收藏”时,我无法在列表中显示“星号”图标(总是显示“star-outline”),尽管我可以从 Firebase 获取这些数据。
到目前为止我已经尝试过这种方式,但没有成功(星形图标在所有项目中保持“star-outline”):
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) };
});
}));
}
您可以使用 rxjs 运算符 switchmap
来实现您的合并行为。 switchmap
允许您使用一个 Observable 的结果,但用另一个 Observable 响应。因此,您可以像以前一样在没有嵌套订阅的情况下链接可观察对象(这通常会导致问题)。这在您的构造函数中看起来像这样:
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);