nareeboy
nareeboy

Reputation: 149

How to return user data from Factory into a controller using Firebase

I have a factory which checks the authData of a user, using firebase. I wish to access the users details such as name, email etc, but I can't figure out how to get the snapshot data into an object which I can use. I'm new to Javascript.

this is my factory:

angular.module('.....')
  .factory('UserDataService', function($q, $firebase, $firebaseAuth, FIREBASE_URL) {
    var authData = {};

    function authDataCallback(authData) {
      if (authData) {
        var ref = new Firebase(FIREBASE_URL + "/userProfiles/" + authData.uid);
        ref.on("value", function(snapshot) {
          var data = snapshot.val();
        });

      } else {
        console.log("User is logged out");
      }
    }

    // Register the callback to be fired every time auth state changes
    var ref = new Firebase(FIREBASE_URL);
    ref.onAuth(authDataCallback);

    return authData;
});

2nd Attempt:

This time i am able to get the users details, but it won't save into the variable service and is returning to the controller as null. Here is my code:

   var firebaseRef = new Firebase(FIREBASE_URL);
    var authObj = $firebaseAuth(firebaseRef);
    activate();
    var service = {
        userInfo: null
    };


    function activate() {
        // Add listeners for authentication state changes
        authObj.$onAuth(function(authData) {
            if (authData) {
                // Load the userInfo
                loadUserInfo(authData);
            } else {
                // Destroy the userInfo Object if one exists
                if (service.userInfo) {
                    service.userInfo.$destroy();
                    service.userInfo = null;
                }
            }
        });
    }

    function loadUserInfo(authData) {
        var userRef = firebaseRef.child('userProfiles').child(authData.uid);
        var loadedInfo = $firebaseObject(userRef);
        // console.log(loadedInfo);

        loadedInfo.$loaded()
        .then(function() {
            service.userInfo = loadedInfo;
            console.log(service.userInfo.name);
        })
        .catch(function(error) {
            switch (error.code) {
                case 'PERMISSION_DENIED':
                    alert('You don\'t have the permission to see that data.');
                    break;
                default:
                    alert('Couldn\'t load the user info.');
            }
        });
    }
    return service;

Upvotes: 0

Views: 1645

Answers (4)

atardadi
atardadi

Reputation: 459

Assuming the snapshot is correct, the val() method turns it into an object. Meaning data now contains the values you need. For example data.name.

The service should expose a function for this

function sendData() {
  var deferred = $q.defer();
  // Register the callback to be fired every time auth state changes
  var ref = new Firebase(FIREBASE_URL);
  ref.onAuth(function(snapshot) {
     deferred.resolve(snapshot.val());
  });

  return deferred.promise;
}

Something like this

Cheers

Upvotes: 0

j2L4e
j2L4e

Reputation: 7050

You assign snapshot.val() to a local variable data. data is destroyed as soon as the function ends.

You need to assign it to the "outer" variable authData, which you can't because you have a function parameter with the same name.

Try it like this:

angular.module('.....')
  .factory('UserDataService', function($q, $firebase, $firebaseAuth, FIREBASE_URL) {
    var authData = {};

    function authDataCallback(data) {
      if (data) {
        var ref = new Firebase(FIREBASE_URL + "/userProfiles/" + data.uid);
        ref.on("value", function(snapshot) {
          authData = snapshot.val();
          //[see comment] var authData = snapshot.val();
        });

      } else {
        console.log("User is logged out");
      }
    }

    // Register the callback to be fired every time auth state changes
    var ref = new Firebase(FIREBASE_URL);
    ref.onAuth(authDataCallback);

    return {
        authData: authData
    };
});

Also you should read up on the return types of service/factory in the docs. What the returned object of a factory does, is basically expose private variables/functions for other modules to access.

Upvotes: 1

Robert Kovacs
Robert Kovacs

Reputation: 361

I suppose there is in var data an object. You can access fields easily with dot .field. For example:

ref.once("value", function(snapshot) {
   var data = snapshot.val();
   // data is { "name": "Fred", "age": 53 }
   // data.name === "Fred"
   // data.age === 53
});

Depending on the data in a DataSnapshot, the val() method may return a primitive (string, number, or boolean), an array, or an object. It may also return null, indicating that the snapshot is empty and contains no data.

Taken from: https://www.firebase.com/docs/web/api/datasnapshot/val.html

I hope it helps.

-EDIT- Use this format to get data in the controller:

var app = angular.module("sampleApp", ["firebase"]);

app.factory("Auth", ["$firebaseAuth",
  function($firebaseAuth) {
    var ref = new Firebase("https://docs-sandbox.firebaseio.com", "example3");
    return $firebaseAuth(ref);
  }
]);

app.controller("SampleCtrl", ["$scope", "Auth",
  function($scope, Auth) {
    $scope.auth = Auth;

    // any time auth status updates, add the user data to scope
    $scope.auth.$onAuth(function(authData) {
      $scope.authData = authData;
    });
  }
]);

Upvotes: 0

Arthur Samarcos
Arthur Samarcos

Reputation: 3299

You need to inject your service inside something (controller, service, filter or directive) and from the controller, call the service function.

.controller('myController', ['UserDataService', function($scope) {
    $scope.userService = UserDataService;
}

Now you can call the function from your controller scope.

userService.authDataCallback()

Upvotes: 1

Related Questions