Issue
I have in Firestore a collection with plants (Where each document represents a plant and each plant has its own attributes like plant ID, name, description, photo URL...) and a collection with users (Where each document represents a user with its own attributes, including an array of objects with the plant IDs of the plants he owns)
What I want to achieve is, for a given user, to give extra details of the plants he owns (not only the ID), these details are in the Plants collection, so I have to perform some kind of inner join operation using the plant id in the user document (Check the UserPlantView interface declaration for the desired output; The attributes image and description would be obtained from the Plants collection)
I read that this is possible using combineLatest and switchMap from rxjs library, but I'm not being able to accomplish it. What I currently have is:
plant-list.page.ts:
import 'firebase/firestore';
import { AngularFirestore } from '@angular/fire/firestore';
import { AngularFireAuth } from '@angular/fire/auth';
import { combineLatest, Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
export interface Plant {
name: string,
pid: string,
image: string,
advices?: string,
care?: string,
clime?: string,
curiosities?: string,
depth?: string,
description?: string,
difficulty?: string,
disease?: string,
germinate?: string,
irrigation?: string,
location?: string,
plant?: string,
reap?: string,
scientific?: string,
season?: string,
temperature?: string,
transplant?: string,
use?: string
}
export interface User {
uid: string,
name: string,
email: string,
plants?: [{
id: string,
plant_name: string,
custom_name: string
}]
}
export interface UserPlantView {
uid: string,
name: string,
plants?: [{
id: string,
plant_name: string,
custom_name: string,
image: string,
description: string
}]
}
@Component({
selector: 'app-plant-list',
templateUrl: 'plant-list.page.html',
styleUrls: ['plant-list.page.scss']
})
export class PlantListPage implements OnChanges {
plantsNames: any;
plantsList = [];
prueba : UserPlantView;
constructor(private AFauth: AngularFireAuth, private firestore: AngularFirestore) {
this.getUsersPlantList();
}
ngOnChanges() {
this.getUsersPlantList();
}
getUsersPlantList() {
const plants : Observable<Plant[]> = this.firestore.collection<Plant>('plantas').valueChanges();
const user : Observable<User> = this.firestore.collection('users').doc<User>(this.AFauth.auth.currentUser.uid).valueChanges();
combineLatest(plants,user).pipe(
switchMap(results => {
const [plantsRes, userRes] = results;
console.log(plantsRes);
console.log(userRes);
// Now I want to form a UserPlantView object using both the user document and the Plants collection...
// ...
return results;
})
).subscribe(data => console.log(data));
}
}
Here you have a screenshot of the console logs, the information is correctly retrieved from Firestore, but I don't know how to keep going. Any help would be much appreciated!
Solution
I finally got what I needed working without the switchMap. Code:
In plant-list.page.ts:
getPlantsList() {
const plants : Observable<Plant[]> = this.firestore.collection<Plant>('plantas').valueChanges();
const user : Observable<User> = this.firestore.collection('users').doc<User>(this.AFauth.auth.currentUser.uid).valueChanges();
combineLatest(plants,user).subscribe(data => {
this.plantUserList = {} as UserPlantView;
this.plantUserList.uid = (<User>data[1]).uid;
this.plantUserList.name = (<User>data[1]).name;
if((<User>data[1]).plants) {
this.plantUserList.plants = new Array();
(<User>data[1]).plants.forEach(element => {
this.plantUserList.plants.push({
id : element.id,
plant_name : element.plant_name,
custom_name : element.custom_name,
image : data[0].find(x=>x.pid == element.id).image,
scientific: data[0].find(x=>x.pid == element.id).scientific
})
});
}
});
}
In plant-list.page.html:
<ng-container *ngIf="plantUserList">
<ion-item *ngFor="let item of plantUserList.plants">
<ion-card ion-button routerLink="/tabs/tab1/{{item.id}}">
<img alt="{{item.plant_name}}" [src]="item.image">
<ion-card-header>
<ion-card-subtitle>20/02/2019</ion-card-subtitle>
<ion-card-title>{{item.custom_name}}</ion-card-title>
</ion-card-header>
<ion-card-content>
<b>{{item.plant_name}}</b> ({{item.scientific}})
</ion-card-content>
</ion-card>
</ion-item>
</ng-container>
Answered By - Markomso
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.