Mapping custom objects to firebase
jaytonic opened this issue ยท 6 comments
Hi,
In my app, I've a collection of object that look like this:
export class Trip {
id: string;
owner: string;
name: string;
startDate: Timestamp;
endDate: Timestamp;
coverImageUrl: string;
itinerary: Itinerary;
constructor() {}
}
export class Itinerary {
stats: ItineraryStats;
steps: Step[];
constructor() {
this.steps = Step[0];
}
}
export abstract class Step {
start: Date;
end: Date;
duration: number;
enforcedStartStop: boolean;
warning: string;
}
//.. then I got concrete objects
When I try to update one trip from my list, I get:
ERROR FirebaseError: Function DocumentReference.set() called with invalid data (via `toFirestore()`). Unsupported field value: a custom object (found in field itinerary in document trips/KBbdsG6GYVCGUYLqKAfe)
at new n (http://localhost:8100/vendor.js:39963:23)
at Gu (http://localhost:8100/vendor.js:53855:16)
at t.i_ (http://localhost:8100/vendor.js:53575:16)
at Mu (http://localhost:8100/vendor.js:53808:37)
at Uu (http://localhost:8100/vendor.js:53692:50)
at http://localhost:8100/vendor.js:53792:17
at _ (http://localhost:8100/vendor.js:40153:68)
at Cu (http://localhost:8100/vendor.js:53791:56)
at Ru (http://localhost:8100/vendor.js:53616:19)
at n.set (http://localhost:8100/vendor.js:55193:40)
Is there a way to map my objects to POJO and then POJO to my objects when using your firestore plugin? What would you recommend me?
hi @jgrossrieder
you can check firebase.firestore.FirestoreDataConverter
export class RacesFirestore extends NgxsFirestore<Race> {
protected path = 'races';
idField = 'raceId';
converter: firebase.firestore.FirestoreDataConverter<Race> = {
toFirestore: (value) => {
const db = { ...value };
delete db.testProp;
return db;
},
fromFirestore: (snapshot, options) => {
const data = snapshot.data(options);
return <Race>{ ...data, testProp: data.id + data.title };
}
};
}
more information here
it's perfect, thank you!
@joaqcid I finally ended by using this to convert my objects to plain json and back:
https://github.com/typestack/class-transformer
It works nicely, I just have a weird issue with dates(if i only convert back and forth using class-transformer, it works, but if it goes to firebase and come back I get an error, like if firebase detects its a date and change its type :'(
Any dates coming back from firestore will be the firebase.firestore.Timestamp
type. It would be worth having a bit of a look into this in the firestore docs on the how and way of this.
I have a few utility methods that I made for converting these dates:
export function isTimestampEqual(
a: Date | firebase.firestore.Timestamp,
b: Date | firebase.firestore.Timestamp
) {
return isEqual(asDate(a), asDate(b));
}
export function asDate(value: any): Date {
if (value && value.toDate) {
return value.toDate();
}
return new Date(value || 0);
}
export function asDateOrNull(value: any): Date | null {
if (!value) {
return value;
}
return asDate(value);
}
export function toFSTimeStamp(date: Date) {
return firebase.firestore.Timestamp.fromDate(date);
}
Hope this helps ๐
@joaqcid Yes I was doing this before, but since now, using class-transformer, I'm only providing a text-format of the date, I was expecting to have a text-format back.
The thing is that class-transformer has a descriptive approach and I was hopping to be able to generate a full "JSON" object out with it that I could have reused at some other places(export/import). I will check if I can create a @FirebaseDate()
descriptor, thanks for the good points.