Search code examples
javascriptangularjsdependency-injectionangularjs-factory

Dependency Injection of functions with Factories (AngularJS)


I have a few functions that are used in different controllers, and rather than copy and paste it multiple times into the controllers, I want to pull it out and place it in a factory.

However, when I try to call the function in the HTML via Angular {{expressions}} it doesn't work.

Instead, I've made functions inside each of the controllers' $scopes that call the factory's functions so the DOM can read the expressions--but that seems redundant. Is there a way to fix this so I can simply call functions from the factory?

Here was what I originally had tried:

index.html:

<div ng-controller="MyController">
    The rating of this item is: {{MakeGraph.getRating(whichItem)}}<br />
    The votes of this item is: {{MakeGraph.getVotes(whichItem)}}
</div>

MyController.js:

controllers.controller('MyController', ['$scope', 'MakeGraph', '$routeParams', function($scope, MakeGraph, $routeParams){
    $scope.whichItem = $routeParams.itemId;
    //no other reference to MakeGraph here
}])

factory.js:

app.factory('MakeGraph', function(){
    var service = {};

    service.getRating = function(itemNo){
        ...
        return ...;
    };

    service.getVotes = function(itemNo){
        ...
        return ...;
    };

    return service;

});

Instead, I can only get it to work when I change MyController to have something like this:

$scope.getRating = function(){
    return MakeGraph.getRating(itemNo);
};

Can I fix this so I don't have to call the function inside the $scope? Thanks.


Solution

  • add $scope.MakeGraph = MakeGraph to your controller

    controllers.controller('MyController', ['$scope', 'MakeGraph', '$routeParams', function($scope, MakeGraph, $routeParams){
        $scope.whichItem = $routeParams.itemId;
        $scope.MakeGraph = MakeGraph
    }])
    

    then you could access MakeGraph from your view

    example:

    <a ng-click="MakeGraph.getVotes(12)"> Click me </a>
    

    note that if you return promises in your service, you will probably still need to wrap then in your controller in order to properly handle the .success / .then / .error ... events