0

I'm new to Angular and I've been struggling for a while trying to call a factory that uses Restangular in one of my controllers. Here is the controller:

'use strict';
angular.module('myApp')
  .controller('UserCtrl', ['WebApi', function($scope, WebApi) {
    $scope.user = WebApi.getProfile(1);
  }
]);

Whenever I call the WebApi factory in my controller, the WebApi object is empty. When I call the method, it will then return undefined. When I log the object in the console, I get

Object {}

Here is my factory:

"use strict";
angular.module("myApp.services", ["restangular"])
  .factory("WebApi", ["Restangular", function(Restangular) {
    var getProfile;
    Restangular.withConfig(function(RestangularConfigurer) {
      RestangularConfigurer.setBaseUrl("http://127.0.0.1:3000/api/v1");
    });
    getProfile = function(id) {
      Restangular.one("users", id).get().then(function(data) {
        return data;
      });
    };
  }
]);

App module:

'use strict';
angular.module('myApp', ['ngCookies', 'ngSanitize', 'ui.router', 'myApp.services']);

And it's included in my index html:

    <script src="scripts/app.js"></script>
    <script src="scripts/controllers/main.js"></script>
    <script src="scripts/services/webapi.js"></script>
    <script src="scripts/controllers/user.js"></script>

What am I doing wrong? Thank you in advance.

John Slegers
  • 45,213
  • 22
  • 199
  • 169
user3181113
  • 758
  • 2
  • 11
  • 23

2 Answers2

2

This one is an async call:

Restangular.one("users", id).get().then(function(data) {
    return data;
  });

and it doesn't return anything to its parent function.

You can return a promise from the parent function, and resolve it inside the then callback I mentioned above (instead of return data;).

The other thing is that factory needs to return an object in order for its properties to be available. There are some really good answers here: angular.service vs angular.factory


UPDATE

Based on the question in the comments, here is what I mean by having to return an object:

angular.module("myApp.services", ["restangular"])
  .factory("WebApi", ["Restangular", function(Restangular) {
    var getProfile;
    getProfile = function(id) {
        // this function is not visible from outside
    };
    // but if you do this:
    return {
        someValue: 3, // accessible via WebApi.someValue
        someFunction: function(){alert('me too')},
        getProfile: getProfile  // now it works as WebApi.getProfile(),
        etc: etc
    }
    // all of these above are now accessible
  }
]);

See the simple example here: http://plnkr.co/edit/KGUqCVJqeEcD5d6m7sVw?p=preview

Community
  • 1
  • 1
Shomz
  • 37,421
  • 4
  • 57
  • 85
  • I understand the difference between a service and factory, but even if I just make a simple function or attribute for `WebApi` and call it from a controller, the `WebApi` object is empty. Why is that? – user3181113 Jun 05 '14 at 08:54
  • Because it needs to be returned, let me show you a simple example to see what I mean. – Shomz Jun 05 '14 at 12:21
0

You should modify your code to use promise and return the promise from there see dummy code

     angular.module("myApp.services", ["restangular"])
              .factory("WebApi", ["Restangular","$q", function(Restangular,$q) {

                Restangular.withConfig(function(RestangularConfigurer) {
                  RestangularConfigurer.setBaseUrl("http://127.0.0.1:3000/api/v1");
                });
                return {
                getProfile : function(id) {
                var deferred = $q.defer();
                  Restangular.one("users", id).get().then(function(data) {
                    deferred.resolve(data);
                  });
                  return deferred.promise;
                };
}

              }
            ]);

        'use strict';
        angular.module('myApp')
          .controller('UserCtrl', ['WebApi', function($scope, WebApi) {
             WebApi.getProfile(1).then(function(data){$scope.user=data});
          }
        ]);
Ajay Beniwal
  • 18,857
  • 9
  • 81
  • 99
  • The console blows up with errors and states `TypeError: undefined is not a function` and points to the `WebApi.getProfile()` function in the `UserCtrl`. I logged the `WebApi` object in the console and it still says `Object {}` – user3181113 Jun 05 '14 at 08:09
  • We are missing return from the factory so i have edited with return could you try now – Ajay Beniwal Jun 05 '14 at 08:26
  • My code is identical to yours, and still, I get `TypeError: undefined is not a function` because the object is empty. It's so weird because the controller knows of the factory and still can't communicate with it. I even put in a simple function that returns `"a string"` and it still does not appear in the `WebApi` object. Do you have any idea why this is? Is it somehow in my dependencies? – user3181113 Jun 05 '14 at 08:43