Angularfire: Using Object Classes

Created on 16 Aug 2016  路  8Comments  路  Source: angular/angularfire

I'm testing Angular 2, Ionic 2, Firebase 3 and Cordova and evaluating if they are a good choice for developing hybrid mobile apps.

I understand that the components have to be separated into different modules is a good practice (SingleReponsibilityPrinciple). Also, in the Angular 2 documentation, following the tutorial, I learn how to define classes in typescript like in object oriented programming.

For example, in the tutorial a Hero class is defined like these:

export class Hero {
聽聽id: number;
聽聽name: string;
}

Is it possible to work with these objects with Firebase?
How should I define my service to return a lista of Heros?

getQuestions (): FirebaseListObservable 聽聽聽af.list return ( '/ heros')
}

or maybe

getHeros (): FirebaseListObservable 聽聽聽af.list return ( '/ heros')
}

Here I attached two posts that say something about it but I do not quite understand what is the best solution:

https://github.com/angular/angularfire2/issues/39
https://github.com/angular/angularfire2/issues/249

Regards,
Alejandro

database

All 8 comments

I also have same question towards using object or not. I tried to use it in my code, but so far it didn't really show any benefit.

The queries returns me list of FirebaseListObervables. So no matter what object/modal I define, doesn't matter, it's a JSON string anyway. In my page, I can format it to my modal, but it doesn't really matter much. If I only update a sub node, from my ts file, I pass the key and value. So far, the modal seems only exists in the page level, not really back to database. From the html page, it's a modal or not doesn't matter at all. I can just pass the key, then it will get me the value.

So after trying it my way, I don't see the value of using modal. Maybe my way is not right. So I'm very interested in the answers coming.

Thanks,
Joyce

@davideast Could you review that?

+1

IMO, the ability to pass in a class is critical to being able to take advantage of ES6 classes here.

af.database.list('/person', Person) : FirebaseListObservable<Person[]>

This would allow us to actually use model objects and consolidate / abstract helper methods within them. There could be an understood contract with any model object that they would supply a constructor that accepts a generic object:

class Person { 
  constructor ( obj : any ) { 
      this.firstName = obj.firstName; 
      this.lastName = obj.lastName;
      ....
  } 
  fullName(){ 
    return this.firstName + ' ' + this.lastName; 
  }
} 

Am i missing another way to accomplish this?

I've run into this some time ago too.

What I did:

  • added a custom operator "mapping" to Observable which will do the heavy work

Of course I still need to define the mapping logic but the calls to af.database.object() and af.databse.list() look much cleaner now:
af.database.list('/person').mapping(mapping).subscribe()

@bohoffi thanks for the input. Do your domain objects extend the FirebaseObjectObservable and use constructors to set properties? Do you mind expanding on your mapping function a bit?

@ekaram of course.
Currently my mapping will output plain JS objects (critic/suggestions are welcome) but I'm planning to extend that to output defined model instances.

The mapping is defined as follows

export interface Mapping {
    [key: string]: (value: any) => any;
}

If I want to map an firebase entity (e.g. a book)

const bookMapping: Mapping = {
    $key: (book) => book.$key,
    isbn: (book) => book.isbn || '',
    title: (book) => book.title || '',
    subTitle: (book) => book.subTitle || '',
    pageCount: (book) => book.pageCount || 0,
    publishDate: (book) => book.publishDate ? new Date(book.publishDate) : new Date(),
    read: (book) => book.read || false,
    shelf: (book) => book.shelf,
    authors: (book) => book.authorMap
};

As you can see the "$value" property will be cut and some properties (e.g. authorMap) will/can be "renamed".

To processing of the mapping is done (in my case wrapped in a custom observable operator) as follows

private _map(value: any, mapping?: Mapping): any {
    return !mapping ? value : Object.keys(mapping).reduce((map, key) => {
        map[key] = mapping[key](value);
        return map;
    }, {});
}

I hope this helps?

I'm currently working on creating an "angularfire2-util" library to provide the mapping (and joining) functionality to other devs (currently heavy WIP).
@davideast I hope this is not a problem?

This is not an issue with AngualrFire2.
You can use classes yourself though mapping functions, however I do not recommend mainly due to the extra overhead, just use simple JavaScript objects, if you need methods make a service to do it.

Can be closed?

Was this page helpful?
0 / 5 - 0 ratings