View on GitHub

Angularfire-resource

Resource factory built on top of AngularFire

Download this project as a .zip file Download this project as a tar.gz file

angularfire-resource

Resource factory built on top of AngularFire

@note This library is under active development and currently not production ready

Abstract

Resource instances are extended firebaseObject, so you'll find everything you're used to with firebase object, plus

AssociationCollection instances are extended firebaseArray, plus

Usage

Add the 'angularfire-resource' module as a dependency to your application module, and then define your model classes and their relations through the FireResource factory

angular.module('myApp', ['angularfire-resource'])

  .factory('$firebase', function() {
    return new Firebase('https://fireresourcetest.firebaseio.com/');
  })

  .factory('User', function(FireResource, $firebase) {
    return FireResource($firebase.child('users'))
      .hasMany('conversations')
      .hasOne('displayedConversation', {className: 'Conversation', inverseOf: false, foreignKey: 'displayedConversationId' })
  })

  .factory('Conversation', function(FireResource, $firebase) {
    return FireResource($firebase.child('conversations'), function(){
      this.hasMany('users');
      // customize the way you store foreign keys to be able to sort your association collection
      this.hasMany('messages', {storedAt: 'createdAtDesc' }, function(baseRef, init){
        // use firebase util to handle the pagination
        init(new Firebase.util.Scroll(baseRef, '$value')).$next(5);  
      });
      // use hooks
      this.beforeCreate(function(){        
        this.createdAtDesc = - Date.now()
      });
    });
  })

  .factory('Message', function(FireResource, $firebase) {
    return FireResource($firebase.child('messages'), function(){
      // define one sided association (ie here no message foreign key will be set into the user model)
      this.hasOne('user', { inverseOf: false }); 
      this.hasOne('conversation');
    });
  })

The above code will maintain a deserialized data model with duplicated foreign keys, to allow security enforcement and easy admin queries.

root
|_ users
| |_ userId1
| | |_ displayedConversationId: conversationId1
| | |_ conversations
| |   |_ conversationId1: true
| |_ userId2
|   |_ conversations
|     |_ conversationId1: true
|
|
|_ conversations
| |_ conversationId1
|   |_users
|   | |_ userId1: true
|   | |_ userId2: true
|   |_ messages
|     |_ messageId1: aCustomValue 
|     |_ messageId2: aCustomValue
|
|
|_ messages
  |_ messageId1
  | |_ userId: userId1
  | |_ conversationId: conversationId1
  |_ messageId2
    |_ userId: userId2
    |_ conversationId: conversationId1

And now you can write some clean controllers :-)

angular.module('myApp')

  // Let's asume $currentUser is an instance of User retrieved from a resolve
  .controller('ExamplesController', function($scope, Message, $currentUser){

    // $query on all ( rootUrl/users ) 
    $scope.allUsers = User.$query()

    // $query on some, customizing your ref
    $scope.someUsers = User.$query(function(baseRef, init){
      init(new Firebase.util.Scroll(baseRef, 'presence')).$next(10)
    });

    // use $next and $prev to access the scroll instance of your custom ref (if firebase util is used)
    $scope.loadMoreUsers = function(){
      $scope.someUsers.$next(10)
    };

    // preload associations
    $scope.conversations = $currentUser.$conversations().$include('messages')

    // Instanciate new model 
    $scope.newMessage = Message.$new()
    $scope.saveMessage = function(){
      angular.extend($scope.newMessage, { userId: $currentUser.$id });

      // save a new instance by adding it to a collection 
      $currentUser.$displayedConversation().$messages().$add($scope.newMessage)
      $scope.newMessage = Message.$new();
    };

    // do sequential operations
    $scope.createConversationWith = function(user) {
      // create an instance into a collection
      return $currentUser.$conversations().$create()
        .then(function (conversation) {
          // then add it to an other collection
          conversation.$users().$add(user);
        })
  })

Demo

To have a more in depth look over a practical case, check out the demo

API / Documentation

... In progress here