A little clarity on getting key values using AngularFire v2?

浪子不回头ぞ 提交于 2019-12-21 03:00:13

问题


Sorry for the length of this but it's driving me a little bit crazy:

Let's say I want to get an item's "title" and ".priority" key values when it loads.

First let's see how every thing's laid out:

 $scope.items = $firebase(new Firebase("https://****.firebaseio.com"));

 $scope.items.$on('loaded', function() { 

console.log($scope.items);

});

With that we get:

> Object {$bind: function, $add: function, $save: function, $set: function, $remove: function…}
    > $add: function (item, cb) {
    > $bind: function (scope, name) {
    > $child: function (key) {
    > $getIndex: function () {
    > $on: function (type, callback) {
    > $remove: function (key) {
    > $save: function (key) {
    > $set: function (newValue) {

    > this is my item: Object
          $$hashKey: "012"
          $id: "this is my item"
          $priority: 2884707
          title: "this is the title of my item"
          __proto__: Object


    > __proto__: Object

Looks good, let's try to grab that $priority:

 console.log($scope.items.$child('$priority'));

Oops:

Uncaught Error: Firebase.child failed: First argument was an invalid path: "$priority". Paths must be non-empty strings and can't contain ".", "#", "$", "[", or "]"

Fine, we'll skip that for now and just try for the title:

console.log($scope.items.$child('title'));

> Object {$bind: function, $add: function, $save: function, $set: function, $remove: function…}
    > $add: function (item, cb) {
    > $bind: function (scope, name) {
    > $child: function (key) {
    > $getIndex: function () {
    > $on: function (type, callback) {
    > $remove: function (key) {
    > $save: function (key) {
    > $set: function (newValue) {
    > __proto__: Object

No title.

Okay, let's try it a different way :

    var firstItem = $scope.items.$getIndex()[0];  //returns $ids in order of priority
     console.log($scope.items.$child(firstItem));

     > Object {$bind: function, $add: function, $save: function, $set: function, $remove: function…}
         > $add: function (item, cb) {
         > $bind: function (scope, name) {
         > $child: function (key) {
         > $getIndex: function () {
         > $on: function (type, callback) {
         > $remove: function (key) {
         > $save: function (key) {
         > $set: function (newValue) {
              title: "this is the title of my item"
         > __proto__: Object

But now there's no priority!

Kitchen sink swearing at the computer time:

 console.log($scope.items.title);

     > undefined

 console.log($scope.items[0].title);

     > Uncaught TypeError: Cannot read property 'title' of undefined 

  console.log(Object.keys($scope.items));     

     > ["$bind", "$add", "$save", "$set", "$remove", "$child", "$on", "$getIndex"]

What am I missing? I can manage to get the 'title' by doing a couple U-turns, (figuring out what the item's $id is using '$getIndex()', grabbing the nth item and then making another call using '$child()' ), but even that doesn't work for $priority. Is there an easier way to get key values from within AngularFire v2? Or any way at all to get the $priority?


回答1:


I believe I am / was experiencing the same issue. Hopefully this is related to your experience. Namely:

$scope.items = $firebase(new Firebase("https://xxxxxx.firebaseio.com"));
$scope.items.$on('loaded', function() {
  console.log($scope.items['some key']); // this writes undefined to console
});

What I noticed is that this actually does work if I don't rely on the loaded event. E.g in the HTML:

<a href="#" data-ng-click="logItem()">click me</a>

and in the JS:

$scope.items = $firebase(new Firebase("https://xxxxxx.firebaseio.com"));
$scope.logItem = function() {
  console.log($scope.items['some key']); // this works
}

Clicking on the "click me" link logs my item to the console as expected.

Feels like the collection at loaded time isn't fully populated with the underlying items from firebase.




回答2:


The $child method should only be used to create a new AngularFire reference. Calling $child is the same as calling $firebase(new Firebase(parentULR + "/childName")). In your example, if all you are trying to do is to get the $priority and title for a given object, you can simply do:

$scope.items = $firebase(new Firebase("https://****.firebaseio.com"));
$scope.items.$on('loaded', function() {
  var item = $scope.items['your-item-id'];
  console.log(item['$priority']);
  console.log(item.title);
});

If you don't know the ID of your item, you can iterate over the $scope.items object to find it if you'd like.




回答3:


As you've noted, your examples are a bit fragmented and there's also no example of your data structure to work from. So it's a bit hard to get a strong picture of what you're trying to accomplish. I'm going to make some assumptions below about all of these things and then offer a working example accordingly. If that doesn't answer the question, maybe it'll help us dig in and find the exact use case you're looking for.

Let's assume, for starters, that we have a list of users at kato.firebaseio.com/users, each of which is an object like so:

/users/:id/name
/users/:id/email
/users/:id/favorite_dessert

Now, let's assume I want to make those work with the following angularCode:

<ul>
  <li ng-repeat="user in users">{{user.name}} really likes {{user.favorite_dessert}}</li>
</ul>

In my controller, I could put something like this:

var fbRef = new Firebase('https://kato.firebaseio.com/users');
$scope.users = $firebase( fbRef );

Now they will automagically appear in my HTML code.

Now, let's assume that when one of these users is clicked, I want to get a two-way binding, which can be edited in a form like this:

<form ng-controller="EditUserController">
      <input ng-model="user.name" type="text" />
      <input ng-model="user.email" type="text" />
      <input ng-model="user.favorite_dessert" type="text" />
</form>

Inside EditUserController I could obtain the user as follows:

var fbRef = new Firebase('https://kato.firebaseio.com/users/'+user_id);
$firebase( fbRef ).$bind($scope, 'user');

Or I could use $child like this (purely to demonstrate usage of $child, not necessary):

var fbRef = new Firebase('https://kato.firebaseio.com/users');
// $child gives a new $firebase object! not a ref to a hash key!
$firebase( fbRef ).$child( user_id ).$bind($scope, 'user');

If I wanted to access any of this data programmatically inside my controller, I could do it like so:

var fbRef = new Firebase('https://kato.firebaseio.com/users');
var usersRef = $firebase( fbRef );
var userId = 'kato';
usersRef.$on('loaded', function() {
   if( usersRef.hasOwnProperty(userId) ) {
      // note that we just grab it by key; not $child!
      var userRecord = usersRef[userId]; 
      console.log(userId + ' was found, name is ' + userRecord.name + ' and priority is ' + userRecord['$priority']);
   }

});


来源:https://stackoverflow.com/questions/20597581/a-little-clarity-on-getting-key-values-using-angularfire-v2

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