装饰AngularFire 3-way数据绑定返回的对象的最佳方法

时间:2014-03-14 11:40:53

标签: angularjs firebase angularfire

我目前的解决方案是使用这样的装饰器函数:

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;      
};
...

1 个答案:

答案 0 :(得分:0)

上述方法的问题在于,只要原始o对象发生更改,它就不会更新。因此,$ scope.decorate返回的t更像是静态快照,而不是Firebase和Angular之间的实时绑定。

一种方法是编写自己的服务。为了简化这个过程,使用双向数据绑定(例如$scope.todos = $firebase(ref))vs 3-way(例如$ firebase(ref)。$ bind($ scope,'todos')`),这将使整个过程适应这一点要简单得多。

示例:

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();

更复杂的方法是使用像Firebase.util这样的连接库,并跳过额外的工作:

// 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 );