0

I've been working on the problem for about a week now with no progress. I have an array of data that's available to my $scope. I iterate through it like this:

<div ng-repeat="device in myData">
    <label>{{processor(device.$id)}}</label>
</div> 

The data contains only a Firebase $uid. And I want to make a second request to the database to get information thats associated with this $uid and place it as the label's content. I thought I could use an angular expression with a function to pass in the Firebase $uid and return some data.

I declare this $scope function:

$scope.processor = function(uid) {
     function getDeviceInfo(callback) {
          _.child('device/' + uid).once('value', function(snapshot) {
               callback(snapshot.val())
          })
     }
     getDeviceInfo(function(data) {
          console.log(data)
          return data
     })
}

Basically I call the processor($id) in my scope, passing in the uid I want to lookup. The function getDeviceInfo() runs and has a callback, when the data is returned, I log it to the console, which works perfect, all the data is there. But then when I try and return a value to the $scope, it doesn't update.

I've tried about every combination of Angular/AngularFire code available and haven't gotten anything to work, any ideas?

3 Answers3

1

Your function is not returning anything. Try this:

$scope.processor = function(uid) {
   function getDeviceInfo(callback) {
     _.child('device/' + uid).once('value', function(snapshot) {
       callback(snapshot.val())
     })
   }
   return getDeviceInfo(function(data) {
     console.log(data)
     return data
   })
}

This seems overcomplicated though, why not do this?

$scope.processor = function(uid) {
  return _.child('device/' + uid).once('value', function(snapshot) {
    return callback(snapshot.val());
  })
}
AJ Funk
  • 3,099
  • 1
  • 16
  • 18
1

If the function that you pass as a parameter to the once function is executed asynchronous, you can't return the data from the processor function.

The best you can do is to add the resulting data to the device object or to create another object to hold all the data for all the devices.

Try this:

<div ng-repeat="device in myData">
    <label>{{device.data}}</label>
</div> 

$scope.processor = function(device) {
   _.child('device/' + device.$id).once('value', function(snapshot) {
           device.data = snapshot.val();
     });
   }
}
$scope.myData.forEach($scope.processor);

Or this:

<div ng-repeat="device in myData">
    <label>{{deviceData[device.$id]}}</label>
</div> 

$scope.deviceData = {};
$scope.processor = function(device) {
   _.child('device/' + device.$id).once('value', function(snapshot) {
           $scope.deviceData[device.$id] = snapshot.val();
     });
   }
}
$scope.myData.forEach($scope.processor);

If that function is not asynch you can return the data using something like this:

$scope.processor = function(uid) {
    var data = undefined;
    _.child('device/' + uid).once('value', function(snapshot) {
        data = snapshot.val()
    })
    return data
}

reference

Community
  • 1
  • 1
Titus
  • 22,031
  • 1
  • 23
  • 33
  • Looked over this, and it does work with what I have, so I'll mark this as my answer, thank you! I did however, after taking a look at this post: http://stackoverflow.com/a/3373953/7371916, find another solution. I'll add it to your post for future users. Thank you VERY much for your help. – Clark McCauley Mar 23 '17 at 19:13
  • @ClarkMcCauley The solution in the answer you've mentioned won't work if the function is asynch. That is because the `processor` function will return before the `data` variable is set. – Titus Mar 23 '17 at 19:19
  • Yeah which has me stumped because the `_.child` firebase query takes time to respond, so how is it working correctly? – Clark McCauley Mar 23 '17 at 19:26
  • 1
    @ClarkMcCauley I'm not sure, I think it works because this code `{{processor(device.$id)}}` is translated to something like `{{someObject.returnValue}}` and when `data` is set, the `someObject.returnValue` is updated. This will definitely not work in vanilla JavaScript. – Titus Mar 23 '17 at 19:30
  • Okay that makes sense. Thanks! – Clark McCauley Mar 23 '17 at 19:33
0

Check whether you have multiple instances of the same controller in your application. I made the same mistake a couple of times. I had ngRoute instantiating the controller using

app.config(function($routeProvider) {
        $routeProvider
            .when('/', {
              //  template : 'NIIIIICE',
                templateUrl : 'pages/enquiries.html',
                controller  : 'firstcontroller'
            });
    });

Then I mistakenly created another instance of the SAME controller inside the HTML like:

ng-controller="firstcontroller as fctrl"

When I call $apply() it would only apply to child instance and that made it seem as if it wasn't working....So yeah long story short make sure you are running $apply in the same instance. :)