Pregunta

My current solution is to use a decorator function like this:

html:

<tr ng-repeat="(id, o) in todos" ng-init="t = decorate(id, o)">
  <td>{{ t.name }}</td>
  <td>{{ t.extra.data }}</td>
  <td><a href="" ng-click="t.remove()">remove</a></td>
</tr>

js:

...
$scope.todos = ... // sets as a firebase 3-ways binding collection

function Todo(id) {
  this.id = id;
}

// remove the todo on firebase
Todo.prototype.remove = function() {
  delete $scope.todos[this.id];
};

// decorate the object fetched by firebase
$scope.decorate = function(id, o) {
  var t = _(new Todo(id)).extends(o);
  // adds some extra data by fetching it from another firebase ref 
  someOtherFirebaseRef.once('value', function(snap) {
    t.extra = snap.val();  
  });
  return t;      
};
...
¿Fue útil?

Solución

The problem with the approach above is that it's not going to get updated whenever the original o object changes. Thus the t returned from $scope.decorate is more like a static snapshot than a real-time binding between Firebase and Angular.

One approach would be to write your own service. To simplify this process, use 2-way data binding (e.g. $scope.todos = $firebase(ref)) vs 3-way (e.g. $firebase(ref).$bind($scope, 'todos')`), which will make the overall process of adapting this much simpler.

Example:

app.factory('DecoratedObject', function($timeout) {
   return function(ref1, ref2) {
      var self = this;
      this.data = {};

      this.getData = function() {
         return data;
      };

      this.save = function(fieldsForRef1, fieldsForRef2) {
         ref1.set( _.pick(data||{}, fieldsForRef1);
         ref2.set( _.pick(data||{}, fieldsForRef2);
      };

      this.dispose = function() {
         ref1.off('value', dataUpdated);
         ref2.off('value', dataUpdated);
      };

      function dataUpdated(snap) {
        // $timeout forces Angular to run $apply and update the DOM
        $timeout(function() {
            _.extend(self.data, snap.val());
        });
      }
   };
});

// and to use it
var obj = new DecoratedObject(ref1, ref2);
$scope.todos = obj.getData();

A more sophisticated approach would be to use a join lib like Firebase.util and skip the extra work:

// create a joined ref between two paths, which behaves just like a single ref
var ref = Firebase.join( ref1, ref2 );

// use it to create your angularFire object
$scope.todos = $firebase( ref );
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top