Cannot set priority on $asObject()'s child keys using Angularfire 0.8

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-24 14:22:38

问题


According to the Angularfire docs, when working with an object returned through $asObject(), you can set priority for said object by defining a $priority property on the object and then using $save().

My code works great, but $priority isn't doing anything. Here's some code with complete explanations in the comments:

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

Yes, I'm following Thinkster.io's tutorial and I'm in Chapter 7. No, this is not a duplicate of the other questions about that chapter, I already found my way around the pre-Angularfire 0.8 code present in their examples, just can't set $priority, and I've spent about 5 hours so far trying to find a solution through my own efforts and on the web.

Any takers?


回答1:


When viewed in the light of how JavaScript works with objects (i.e. unordered), how JSON handles objects (i.e. unordered), and in light of the expectation that AngularFire's $asObject() method is intended for storing key/value pairs, and singular records that are not used as a collection, this starts to make some sense.

Internally, the synchronize'd object's $save method calls Firebase's setWithPriority. In set or setWithPriority calls, the child nodes are replaced. Any meta data like priorities on those children are replaced.

In AngularFire, $asArray is intended to handle ordered collections, and provides the ability to set $priority on child nodes (only one level deep, of course, as it treats its children as singular records that are not themselves collections).

Since, in your case, you want to work with fixed keys rather than push ids, you'll probably want to override the $add method using $extendFactory and do something like the following:

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

You could then pass this into your $firebase instance in place of the default factory:

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

A simpler but less awesomatic™ solution would be to manually add your objects to the array, manually giving them a $id, then call $save:

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

Some notes on the future: It will soon be possible to use any field as sort criteria and there will be no need to set priorities (yay!). It will probably be possible to set your own $id before calling $add on a synchronized array in AngularFire as soon as I clear that with the other devs (like the 0.8.3 release).



来源:https://stackoverflow.com/questions/25674894/cannot-set-priority-on-asobjects-child-keys-using-angularfire-0-8

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!