I am working on an Angular 2 app with Typescript and I'm constantly having issues with the fact that when I cannot seem to persist object types very easily when syncing data.
I have been manually setting properties. In some cases I'm just removing the $exists(), $key, createdat functions and properties to be able to update the data.
Is there a way to set a class from a Firebase object without completely changing it?
For an example:
search$:FirebaseObjectObservable<ISearchQuery>;
search:ISearchQuery;
constructor(public af: AngularFire, public auth: AuthService){
this.search$ = this.af.database.object(`/queries/saved/${auth.id}`);
//THIS IS HOW I WANT TO DO IT
this.search$.subscribe((data)=>{
if(data.$exists()){
this.search=data;
}
});
//THIS IS WHAT I'VE RESORTED TO
this.search$.subscribe((data)=>{
if(data.$exists()){
this.search.categories = data.categories;
this.search.creators = data.creators;
this.search.endDate = data.endDate;
this.search.startDate = data.startDate;
this.search.location = data.location;
}
});
}
On the flip side when I've synced and updated data then I have to pick each property when updating or setting to firebase. I also run into issues if I sync directly I lose class functions as well (since firebase objects have their own set of functions in the prototype).
Is there a way to avoid picking property by property or a better way of dealing with syncing Firebase objects with Typescript?
It sounds like you want AngularFire2 to preserve the Firebase snapshots. By default, it 'unwraps' the snapshots, adding the $
-prefixed property and function that you do not want.
If you specify the preserveSnapshot
option, it won't do this and you can call snapshot.val()
:
constructor(public af: AngularFire, public auth: AuthService) {
this.search$ = this.af.database.object(`/queries/saved/${auth.id}`, {
preserveSnapshot: true
});
this.search$.subscribe((snapshot) => {
if(snapshot.exists()) {
this.search = snapshot.val();
}
});
}
And if you are going to need it later, you can always keep the snapshot.
Regarding ISearchQuery
- which I am assuming is an interface - the value you receive from snapshot.val()
is an anonymous object. It's safe to cast it to an interface that describes the 'shape' of the data, but if that interface includes methods, it is not going to work because the methods will not exist on the anonymous object. If you have a class that implements that interface, you should include a constructor that accepts the anonymous object you receive from snapshot.val()
.
For example:
this.search$.subscribe((snapshot) => {
if(snapshot.exists()) {
// Given SomeSearchQuery implements ISearchQuery
this.search = new SomeSearchQuery(snapshot.val());
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With