texas697
texas697

Reputation: 6417

how to retrieve data by id with angularfire

i used a tutorial to create a angularfire chat app. it is a standalone app that uses ui-router. I integrated it succssfully as a view in my app but that is not practical. I need to be able to use the chat on any view I am at. I am stuck at moving a resolve function to a controller. I have read some docs and I believe it is returning a promise that I need to resolve in the controller. the link to the tutorial is here. tutorial

here is the ui-router I am trying to get away from

.state('channels.direct', {
                 url: '/{uid}/messages/direct',
                 templateUrl: 'views/chat/_message.html',
                 controller: 'MessageController',
                 controllerAs: 'messageCtrl',
                 resolve: {
                     messages: function ($stateParams, MessageService, profile) {
                         return MessageService.forUsers($stateParams.uid, profile.$id).$loaded();
                     },
                     channelName: function ($stateParams, UserService) {
                         return UserService.all.$loaded().then(function () {
                             return '@' + UserService.getDisplayName($stateParams.uid);
                         });
                     }
                 }
             })

The message service

  var channelMessagesRef = new Firebase(AppConstant.FirebaseUrl + 'channelMessages');
    var userMessagesRef = new Firebase(AppConstant.FirebaseUrl + 'userMessages')

    return {
        forChannel: function (channelId) {
            return $firebaseArray(channelMessagesRef.child(channelId));
        },
        forUsers: function (uid1, uid2) {
            var path = uid1 < uid2 ? uid1 + '/' + uid2 : uid2 + '/' + uid1;

            return $firebaseArray(userMessagesRef.child(path));
        }
    };

the user service

 var usersRef = new Firebase(AppConstant.FirebaseUrl + 'users');
    var connectedRef = new Firebase(AppConstant.FirebaseUrl + '.info/connected');
    var users = $firebaseArray(usersRef);
    return {
        setOnline: function (uid) {
            var connected = $firebaseObject(connectedRef);
            var online = $firebaseArray(usersRef.child(uid + '/online'));

            connected.$watch(function () {
                if (connected.$value === true) {
                    online.$add(true).then(function (connectedRef) {
                        connectedRef.onDisconnect().remove();
                    });
                }
            });
        },
        getGravatar: function (uid) {
            return '//www.gravatar.com/avatar/' + users.$getRecord(uid).emailHash;
        },
        getProfile: function (uid) {
            return $firebaseObject(usersRef.child(uid));
        },
        getDisplayName: function (uid) {
            return users.$getRecord(uid).displayName;
        },
        all: users
    };

here is what I have so far in the controller

 $scope.directMessage = function (uid) {
        UserService.all.$loaded().then(function () {
            $scope.selectedChatUser = '@' + UserService.getDisplayName(uid);
        });
        $scope.selectedChatUserMessages = MessageService.forUsers(uid, profile.$id).$loaded();
    };

I am returning the

$scope.selectedChatUser

fine. the issue is with the Message Service

this is the what i am currently returning from the message service

$$state: Object
__proto__: Promise

how do i resolve this?

Upvotes: 1

Views: 387

Answers (1)

David East
David East

Reputation: 32624

You're trying to return from inside a promise in your channelName function.

The object you're getting back is an unresolved promise. You want the resolved data from the promise injected into your controller.

You need to create a to return from this function.

.state('channels.direct', {
   url: '/{uid}/messages/direct',
   templateUrl: 'views/chat/_message.html',
   controller: 'MessageController',
   controllerAs: 'messageCtrl',
   resolve: {
      messages: function ($stateParams, MessageService, profile) {
        return MessageService.forUsers($stateParams.uid, profile.$id).$loaded();
      },
      channelName: function ($stateParams, UserService, $q) {
         // create a deferred for this function
         var deferred = $q.defer();
         // load async data with UserService.all's promise
         UserService.all.$loaded()
           .then(function () {
              var name = UserService.getDisplayName($stateParams.uid);
              deferred.resolve(name);  
           });
         // return promise
         return deferred.promise;
      }
   }
})

However in getDisplayName I would just recommend returning back the object rather than just the name, as the entire set is synchronized by Firebase.

Upvotes: 2

Related Questions