Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

I am trying to include a library of functions, held in a factory, into a controller. Similar to questions like this: AngularJS - Common controller functions

My main controller looks like this:

recipeApp.controller('recipeController', function ($scope, groceryInterface, ...){

$scope.groceryList = [];
// ...etc...    

/* trying to retrieve the functions here */
$scope.groceryFunc = groceryInterface; // would call ng-click="groceryFunc.addToList()" in main view
    /* Also tried this:
    $scope.addToList = groceryInterface.addToList();
    $scope.clearList = groceryInterface.clearList();
    $scope.add = groceryInterface.add();
    $scope.addUp = groceryInterface.addUp(); */
}

Then, in another .js file, I have created the factory groceryInterface. I've injected this factory into the controller above.

Factory

recipeApp.factory('groceryInterface', function(){

        var factory = {};

    factory.addToList = function(recipe){
        $scope.groceryList.push(recipe);
                    ... etc....
    }

    factory.clearList = function() {
            var last = $scope.prevIngredients.pop();
            .... etc...
    }

    factory.add = function() {
    $scope.ingredientsList[0].amount = $scope.ingredientsList[0].amount + 5;
    }

    factory.addUp = function(){
        etc...
    }

    return factory;
});

But in my console I keep getting ReferenceError: $scope is not defined at Object.factory.addToList, etc. Obviously I'm guessing this has to do with the fact that I'm using $scope in my functions within the factory. How do I resolve this? I notice that in many other examples I've looked at, nobody ever uses $scope within their external factory functions. I've tried injecting $scope as a parameter in my factory, but that plain out did not work. (e.g. recipeApp.factory('groceryInterface', function(){ )

Any help is truly appreciated!

share|improve this question
up vote 20 down vote accepted

Your factory can't access your $scope, since it's not in the same scope.

Try this instead:

recipeApp.controller('recipeController', function ($scope, groceryInterface) {

    $scope.addToList = groceryInterface.addToList;
    $scope.clearList = groceryInterface.clearList;
    $scope.add       = groceryInterface.add;
    $scope.addUp     = groceryInterface.addUp;
}

recipeApp.factory('groceryInterface', function () {

    var factory = {};

    factory.addToList = function (recipe) {
        this.groceryList.push(recipe);
    }

    factory.clearList = function() {
        var last = this.prevIngredients.pop();
    }
});

Alternatively, you can try using a more object oriented approach:

recipeApp.controller('recipeController', function ($scope, groceryInterface) {

    $scope.groceryFunc = new groceryInterface($scope);
}

recipeApp.factory('groceryInterface', function () {

    function Factory ($scope) {

        this.$scope = $scope;
    }

    Factory.prototype.addToList = function (recipe) {
        this.$scope.groceryList.push(recipe);
    }

    Factory.prototype.clearList = function() {
        var last = this.$scope.prevIngredients.pop();
    }

    return Factory;
});
share|improve this answer
    
Sweet, thank you. I will try this out! – Gnuey Oct 28 '13 at 18:23
2  
@Gnuey - Note that bind is not available in older versions of IE. If you have to support those and want to use the first method, either use this MDN polyfill, or - if you have jQuery on the page - use $.proxy instead. – Joseph Silber Oct 28 '13 at 18:26
1  
Okay, great. That is actually extremely helpful info -- my dept head and site visitors use older IE versions at times for some reason :\ Would I instead write $scope.addToList = $.proxy(groceryInterface.addToList, $scope) ? – Gnuey Oct 28 '13 at 18:32
1  
@Gnuey - Yes. Exactly like that. – Joseph Silber Oct 28 '13 at 18:48
    
Hmm, I am getting TypeError: Cannot call method 'push' of undefined at Object.factory.addToList I forgot to mention that groceryList is an array in the main controller ($scope.groceryList = []). Does this make a difference? – Gnuey Oct 28 '13 at 22:22

You cannot use $scope in a factory as it is not defined. Instead, in your factory functions change the properties of the object the factory is returning, e.g.

factory.addToList = function (recipe) {
    this.groceryList.push(recipe);
}

these will then get passed on to your $scope variable

$scope.addToList = groceryInterface.addToList;
// ... = groceryInterface.addToList(); would assign to `$scope.addToList` what is returned, instead of the function itself. 
share|improve this answer
    
Thanks, I will try this out! – Gnuey Oct 28 '13 at 18:27
1  
I edited your solution so that instead of $scope.addToList = groceryInterface.addToList();, it reads $scope.addToList = groceryInterface.addToList; I discovered that the parenthesis at the end of addTotList() was one big problem during my debug process... got myself quite a nice refreshing slap of javascript syntax... – Gnuey Oct 31 '13 at 3:34

This isn't the exact answer for this question, but I had a similar issues that I solved by simply passing $scope as an argument to a function in my factory. So it won't be the normal $scope, but $scope at the time the function in the factory is called.

app.controller('AppController', function($scope, AppService) {


  $scope.getList = function(){

    $scope.url = '/someurl'

    // call to service to make rest api call to get data

    AppService.getList($scope).then(function(res) {
      // do some stuff 

    });
  }

});


app.factory('AppService', function($http, $q){
  var AppService = {

    getList: function($scope){
      return $http.get($scope.url).then(function(res){
        return res;
      });
    },

  }

  return AppService;
});
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.