无法使用Angularfire 0.8在$ asObject()的子键上设置优先级

时间:2014-09-04 20:59:04

标签: angularjs firebase angularfire firebasesimplelogin

根据Angularfire文档,在处理通过$asObject()返回的对象时,您可以通过在对象上定义$priority属性然后使用$save()来设置所述对象的优先级。

我的代码效果很好,但$priority并没有做任何事情。这里有一些代码在评论中有完整的解释:

app.factory('MyService', function($rootScope, $firebase) {

  // The complete Firebase url
  var ref = *obfuscated*;

  // Returning the dataset as an object containing objects
  var data = $firebase(ref).$asObject;

  // This object is what's returned by MyService
  var Data = {

    // Method to create a new object within the data set,
    // keyed by myId. Attempting to set priority for the
    // record via $priority. returnData.uid is a valid string.
    create: function(returnData, myId) {
      data[myId] = {
        myId: myId,
        $priority: returnData.uid
      };

      // No need to explain the stuff between here and the
      // $rootScope listener below, just added for context
      data.$save().then(function() {
        setMyId(myId);
      });
    },
    findByMyId: function(myId) {
      if (myId) {
        return data[myId];
      }
    }
  };

  function setMyId(myId) {
    $rootScope.myId = User.findByMyId(myId);
  }

  // This event listener works fine, fires
  // at user login and returns data
  $rootScope.$on('$firebaseSimpleLogin:login', function(e, returnData) {

    // returnData.uid has the correct value - this
    // function should return the object(aka record) with
    // a priority matching returnData.uid
    var query = $firebase(ref.startAt(returnData.uid).endAt(returnData.uid)).$asObject();

    // console shows an object with the normal $firebase
    // properties, but no records. If I define query without
    // limiting the set ($firebase(ref).$asObject()), it returns
    // the full set just fine. The priority on all records is still
    // null.
    console.log(query);    

    query.$loaded(function() {
      setData(query.myId);
    });
  });

  return Data;
});

是的,我正在关注Thinkster.io的教程和我在第7章。不,这不是关于该章的其他问题的重复,我已经找到了解决方法他们的例子中出现的前Angularfire 0.8代码,只是无法设置优先权,到目前为止,我花了大约5个小时试图通过自己的努力和网络找到解决方案。

任何参赛者?

1 个答案:

答案 0 :(得分:3)

根据JavaScript如何处理对象(即无序),JSON如何处理对象(即无序),并考虑到AngularFire的$asObject()方法的预期for storing key/value pairs, and singular records that are not used as a collection,这开始有道理。

在内部,同步对象的$save方法会调用Firebase的setWithPriority。在setsetWithPriority调用中,将替换子节点。这些孩子的优先级等元数据都会被替换。

在AngularFire中,$asArray旨在处理有序集合,并提供在子节点上设置$priority的能力(当然,只有一级深度,因为它将其子节点视为单个记录,不是自己的收藏品。)

因为在你的情况下,你想要使用固定键而不是push id,你可能想要使用$ extendFactory覆盖$ add方法并执行以下操作:

angular.module(MY_APP).factory('FixedKeysFactory', function($FirebaseArray, $firebaseUtils) {
  return $FirebaseArray.$extendFactory({
    $add: function(data) {
      this._assertNotDestroyed('$add');
      if( angular.isObject(data) && typeof data.$id === 'string' ) {
        return this.$inst().$set(data.$id, $firebaseUtils.toJSON(data));
      }
      else {
        return this.$inst().$push($firebaseUtils.toJSON(data));
      }
    }
  });
});

然后,您可以将其传递到$ firebase实例中,而不是默认工厂:

var list = $firebase(ref, {arrayFactory: FixedKeysFactory}).$asArray();

一个更简单但不那么awesomatic™的解决方案是手动将对象添加到数组中,手动给它们一个$ id,然后调用$ save:

var list = $firebase(ref).$asArray();
var i = list.length;
list.push({ foo: 'bar', $id: 'kato' });
list.$save(i);

关于未来的一些注释:很快就可以使用任何字段作为排序标准,并且不需要设置优先级(耶!)。一旦我用其他开发者(如0.8.3版本)清除它,就可以在AngularFire中的同步数组上调用$ add之前设置自己的$ id。