theFish
theFish

Reputation: 123

Making the most of my factory

I am new to Angular, so if you ask the question: "Why don't you...?" The answer is...because I didn't know I could.

Have a factory make an API call, then inject that factory into a parent controller that will have scope over the entire page. Then have child controllers nested and inherit from the parent controller.

Here is what I have so far. I may be WAY off here, and if that is the case, please tell me. I am working on this alone, and have no help, so any help is welcomed.

Thank you.

var app = angular.module('myApp', []);

app.factory('myFactory', function($http){
    var MyFactory = function(){};

    MyFactory.getParams = function(){
        return $http.get('/getparameters');
        .success(function(data){
            var roomname = data.roomname;
        })
        MyFactory.getRoom(roomname);
    };

    MyFactory.getRoom = function(room){
        return $http.get('/my/api/' + room);
    };


});

app.controller('RoomCtrl', function($scope, myFactory){
    $scope.data = myFactory;        
});

Upvotes: 1

Views: 73

Answers (3)

Mehmet Otkun
Mehmet Otkun

Reputation: 1384

You don't need to use resource, you need use promise; EDITED I tried to make more clear for you

app.factory('apicall', ['$q','$http',function($q, $http){

    function getRoom(options){
      var promise =  $http.get(options.paramUrl)
                    .success(function(data){
                         //handle your error
                         return $http.get(options.roomUrl + data.roomname);              
                     })
                     .error(function(msg){
                          return $q.when(msg)
                      })   
           return promise;
    }

   return {getRoom:getRoom};
 }])

if you want call your factory in where you want

app.controller('RoomCtrl', ['$scope','apicall',function($scope, apicall){
       var options = {
                        paramUrl:'/getparameters',
                        roomUrl:'/my/api/'
                     }
       apicall.getRoom.all(function(result){
            $scope.data = result; 
        })

  }]);

Upvotes: 0

Cristi Berceanu
Cristi Berceanu

Reputation: 1693

I usually separate different API calls in different factories that return a $resource.

For example, let's say we have 2 different API calls that point to different resources:

yourwebsite.com/user/:userId - returns data about the user

yourwebsite.com/photo/:photoId - return data about some photo

In angular, you would split these in 2 different factories: "use strict";

angular.module("App.services").
factory("User",["$resource", function($resource){
    return $resource("yourwebsite.com/user/:userId"),{userId:"@userId"});
}]);

and second

angular.module("App.services").
factory("Photo",["$resource", function($resource){
    return $resource("yourwebsite.com/photo/:photoId"),{photoId:"@photoId"});
}]);

In your controller, you would use them like so:

angular.module("App.controllers").controller("TestController",["User","Photo", function(User, Photo){
    User.get({
        id:10
    }).$promise.then(function(data){
            console.log(data); //returns the data for user with the id=10
        });

    Photo.get({
            id:123
    }).$promise.then(function(data){
                console.log(data);
    });

}]);

Usually $resource maps a CRUD API(what I posted above is a basic example of a GET call).Check out the documentation on $resource - It already has the basic GET, PUT, POST, DELETE functions.

I would recommend using $http if you have only 1 simple operation on that URL and not all 4 of them. You can then inject $http in your controller and do the request there instead of creating a factory for it.

If you have 2 requests and they are chained(second one depends on the data received from the first one) you have to wait until the first one is resolved. With $resource you can do this in the following way:

angular.module("App.controllers").controller("TestController",["User","Photo", function(User, Photo){
        var user_promise = User.get({
            id:10
        }).$promise.then(function(data){
                console.log(data); //returns the data for user with the id=10
                return data;

            });

        var photo_promise = Photo.get({
                id:123
        }).$promise.then(function(data){
                    console.log(data);
                    return data;
        });

     user_promise.then(photo_promise).
      catch(function(error){
        console.log(error); //catch all errors from the whole promise chain
     });

    }]);

Upvotes: 0

Ilya
Ilya

Reputation: 326

The $q service helps you to handle combination of two asynchronous calls

app.factory('apicall', function($q, $http) {
  var deferred = $q.defer();

  $http.get('/getparameters')
    .success(
      function(data) {
        var roomname = data.roomname;
        $http.get(baseURL + 'room/' + roomname)
          .success(
            function(roomData) {
              deferred.resolve(roomData);
            }
        )
          .error(
            function() {
              deferred.reject();
            }
        )
      })
    .error(
      function() {
        deferred.reject();
      }
  );

  return deferred.promise;
});

And here is controller where you can use your service

app.controller('someCtrl', function(apicall) {
  apicall.then(
    function(roomData) {
      //success
    },
    function() {
      //error
    }
  )
})

Upvotes: 0

Related Questions