Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make controller wait for service to return a value and how to access the returned value in controller?

I am new to angularjs. I am having trouble in accessing value that is returned from angularjs service in its controller. Following is the code in controller:

'use strict';
app.controller('AdminTaskCtrl', function ($scope, Search) {
    $scope.buildEnquiry = function (collegeId, ) {
        Search.getIdByEmail(collegeId).then ( function ( result ) {
            $scope.uId = result;
            console.log($scope.uId);
        });
    };
});//controller ends here

And the code in Search service is as follows:

'use strict';
           app.factory('Search',function ($firebase, FIREBASE_URL, $rootScope) {
                          var simpleuser = "";
                          getIdByEmail: function(counsellorEmail) {
                          var collegeuserArray = ($firebase(new Firebase(FIREBASE_URL+"abc/def/")).$asArray());
                          collegeuserArray.$loaded(function(collegeuserArray) {
                              for(var i=0; i<collegeuserArray.length; i++) 
                              {
                                if((collegeuserArray[i].$value) == counsellorEmail)
                                {
                                     simpleuser = collegeuserArray.$keyAt(collegeuserArray[i]);
                                     console.log(simpleuser);
                                     return simpleuser;
                                }
                              }
                          }, function(error) {
                              console.error("Error:", error);
                          });
                    }
                  };     
            );//service ends here.

When the code executes it gives error for .then function as fallows:

TypeError: undefined is not a function and value in controller is not accessed.

Please help.

like image 759
Ashutosh Pradhan Avatar asked Feb 17 '15 12:02

Ashutosh Pradhan


2 Answers

'use strict';
       app.factory('Search',function ($firebase, FIREBASE_URL, $rootScope, $q) {
                      var simpleuser = "";
                      getIdByEmail: function(counsellorEmail) {
                      var deferred = $q.defer();
                      var collegeUserArray = ($firebase(new Firebase(FIREBASE_URL+"abc/def/")).$asArray());
                      collegeUserArray.$loaded(function(collegeUserArray) {
                          for(var i=0; i<collegeUserArray.length; i++) 
                          {
                            if((collegeUserArray[i].$value) == counsellorEmail)
                            {
                                 simpleUser = collegeUserArray.$keyAt(collegeUserArray[i]);
                                 console.log(simpleUser);
                                 //return simpleUser;
                                 deferred.resolve(simpleUser);
                            }
                          }
                      }, function(error) {
                          console.error("Error:", error);
                          deferred.reject(error);
                      });
                      return deferred.promise;
                }
              };     
        );

And your controller

'use strict';
app.controller('AdminTaskCtrl', function ($scope, Search) {
  $scope.buildEnquiry = function (collegeId, ) {
    Search.getIdByEmail(collegeId).then ( function ( result ) {
        $scope.uId = result;
        console.log($scope.uId);
    }, function(error){
        //If an error happened, handle it here
    });
  };
});
like image 136
Deblaton Jean-Philippe Avatar answered Oct 13 '22 05:10

Deblaton Jean-Philippe


To directly answer your question, $loaded returns a promise, so the simplest answer here would be to return it from your service instead of bothering with $q and all these other things.

It does seem like the whole premise here is flawed and that this is an XY problem. It seems like several hacks intended to subvert the intended usage of these libs, and like a good, solid read of the Angular walkthrough and the AngularFire guide would save a lot of pain and needless complexity here.

The use of factory here is a subversion and heavily coupled. The syntax is invalid and wouldn't compile. And ultimately, the goal is to add a search method to the synchronized array returned from AngularFire, which should be done with $extendFactory.

app.factory('firebaseRef', function(FIREBASE_URL) {
   return function(path) {
      var ref = new Firebase(FIREBASE_URL);
      if( path ) { ref = ref.child(path); }
      return ref;
   }
});

app.factory('SearchableArray', function($firebase, $FirebaseArray) {
   var ArrayWithSearch = $FirebaseArray.$extendFactory({
     searchByEmail: function(emailAddress) {
        var res = null;
        for(var i=0, len=this.$list.length; i < len; i++ ) {
           if( this.$list[i].email === emailAddress ) {
              res = this.$list[i];
              break;
           }
        }
        return res;
     }
   });

   return function(ref) {
      return $firebase(ref, {arrayFactory: ArrayWithSearch}).$asArray();      
   }
});

app.controller('Controller', function($scope, SearchableArray, firebaseRef) {
   $scope.data = SearchableArray( firebaseRef('abc/def') );

   $scope.search = function(email) {
      console.log( $scope.data.searchByEmail(email) );
   };
});
like image 23
Kato Avatar answered Oct 13 '22 05:10

Kato