I have a model of subject events - defines what properties it should have:
export class EventSchema {
title: string;
start: string;
end: string;
price: number;
constructor(title: string, start: string, end: string, price: number){
this.title=title;
this.start=start;
this.end=end;
this.price=price;
}
}
I have another model that encapsulates the above model - has a subject name and the event properties in an array since there can be multiple events for a single subject:
import { EventSchema } from './eventSchema.model';
export class SubjectEvents {
subjectName: string;
eventData: EventSchema[];
constructor(subjectName: string, eventData: EventSchema[]){
this.subjectName=subjectName;
this.eventData=eventData;
}
}
I have a collection in firebase matching these models. So far there are only two documents, one with maths subjects and one with physics subjects, each with 2 events. Example data is:
I have this service which gets the data, and transforms it. In this instance, I want to take each event for a subject (document) and put it into one big array. Maybe I need to merge the output of each document... not sure how. I am able to achieve this somewhat - but the results are coming out duplicated, and I don't understand why. Please see below a screen shot of the final output.
import { Injectable } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument, QuerySnapshot, QueryDocumentSnapshot } from 'angularfire2/firestore';
import { Observable, of, Subscription } from 'rxjs';
import { map, filter } from 'rxjs/operators';
import 'rxjs/add/operator/mergeMap';
import { SubjectEvents } from '../_models/subjects/subjectEvents.model';
import { EventSchema } from '../_models/subjects/eventSchema.model';
@Injectable()
export class SubjectEventsService {
subjectEventCollection : AngularFirestoreCollection<SubjectEvents>;
subjectEventDocument : AngularFirestoreDocument<SubjectEvents>;
subjectEvents : Observable<SubjectEvents[]>;
subjectEvent : Observable<SubjectEvents>;
filteredArr : Observable<any[]>;
constructor(private afs : AngularFirestore) {
//Get user collection on initialise
this.subjectEventCollection = this.afs.collection('subjectEvents');
}
getSubjectEvents(subjectFilter: string): Observable<SubjectEvents[]> {
this.filteredArr = this.subjectEventCollection.snapshotChanges()
.pipe(map(changes => {
let filteredArr : any = [];
console.log(filteredArr);
return changes
.map(action => {
console.log(action);
const data = action.payload.doc.data() as SubjectEvents;
data.subjectName = action.payload.doc.data().subjectName;
data.eventData = action.payload.doc.data().eventData;
console.log(data);
data.eventData.forEach(result => {filteredArr.push(result); console.log(filteredArr)});
return filteredArr;
});
}));
return this.filteredArr;
}
}
.pipe(mergeMap(changes...
orreturn changes.pipe(mergeMap(action...
because changes is anObservable<SubjectEvents[]>
and you want to unwind that array toObservable<SubjectEvents>
. It helps with reasoning if you type your parameters. (BTW perhaps bad form to mix pipable operators and non-pipable operators). - Richard Matsen