0

I want to share so functions across my app, for which I have few factories. The issue is I have to add all these factories in every controller whenever required. With increasing number of factories & controllers this is tedious task!

Thus I was trying to find a way to reduce this redundancy. In browsing SO for same, I came across following question:

Can I make a function available in every controller in angular?

This is what I am looking for, And the below answer look most suitable for me:

https://stackoverflow.com/a/24714658/3375368


Now I want to go one step ahead by removing need of inserting $rootScope!

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
        var myApp = angular.module('myApp', []);

        myApp.factory('myService', function() {
            return {
                foo: function() {
                    alert("I'm foo!");
                }
            };
        });

        myApp.run(function($rootScope, myService) {
            $rootScope.appData = myService;
        });

        myApp.controller('MainCtrl', ['$scope', '$rootScope', function($scope, $rootScope){

            appData.foo() //This wont work
            $rootScope.appDate.foo() //This will work

            //Is there a way to remove dependancy on $rootScope??

        }]);

    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="appData.foo()">Call foo</button>
    <!-- This works, but I wont be using this, its from original post -->
</body>
</html>

Another question is whether this approach is good? & how it will affect the working of factory data sharing, i.e. are there any pitfalls?

Community
  • 1
  • 1
demonofthemist
  • 4,081
  • 4
  • 26
  • 45
  • 1
    Probably not a good idea to have your view directly calling your services. Why do you want to remove the `$rootScope` dependency? – JLRishe Apr 03 '17 at 08:29
  • @JLRishe, to reduce dependancy injection if possible – demonofthemist Apr 03 '17 at 08:32
  • @JLRishe I am quite new to angularjs, just started to explore it in depth, if this is the appropriate way to do thing then I am okay with it, I am just curious if I can be done in other way & what are consequences! – demonofthemist Apr 03 '17 at 08:34
  • 1
    Probably not a good idea to even keep all functions in `$rootScope` either.. – tanmay Apr 03 '17 at 08:34
  • @tanmay can you eloborate?, because I don't understand why? Because its regular factory system & $rootScope only contain the instance of factories which are then shared by all the controllers. – demonofthemist Apr 03 '17 at 08:36
  • @demonofthemist You should avoid loading a ton of stuff onto `$rootScope` for the same reason that you should avoid global variables. '$rootScope` isn't just a dumping ground for placing a bunch of stuff you want to share around. – JLRishe Apr 03 '17 at 08:42

1 Answers1

2

If your services are on the $rootScope, then they should be accessible from the $scope. So there's no need to include a dependency on $rootScope:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
        var myApp = angular.module('myApp', []);

        myApp.factory('myService', function() {
            return {
                foo: function() {
                    alert("I'm foo!");
                }
            };
        });

        myApp.run(function($rootScope, myService) {
            $rootScope.appData = myService;
        });

        myApp.controller('MainCtrl', ['$scope', function($scope){
            $scope.appData.foo() //This will work
        }]);

    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="appData.foo()">Call foo</button>
    <!-- This works, but I wont be using this, its from original post -->
</body>
</html>

However, it's not a good idea to load all of that stuff onto the $rootScope. AngularJS's dependency injection system exists for a reason, but if you really really want to avoid actually using services as they were intended, then you could create an aggregate service that contains all the others:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
        var myApp = angular.module('myApp', []);

        myApp.factory('myService', function() {
            return {
                foo: function() {
                    alert("I'm foo!");
                }
            };
        });

        myApp.factory('allMyServices', ['myService', function (myService) {
            return {
                myService: myService
            };
        }]);
        myApp.controller('MainCtrl', ['$scope', 'allMyServices', function($scope, allMyServices){
            allMyServices.myService.foo() //This will work
        }]);

    </script>
</head>
<body ng-controller="MainCtrl">
</body>
</html>
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • Thanks for the effort. One query thought, How individual dependancy injection is different than this second approach? – demonofthemist Apr 03 '17 at 08:49
  • @demonofthemist in the second approach, you need to inject only `allMyServices` as dependency, so the _tedious_ task of injecting all different services into controllers is resolved – tanmay Apr 03 '17 at 09:03
  • @tanmay :D, Yes thats the major point! But I was asking since we are not using the services as they are intended, is there any difference in working or behaviour? – demonofthemist Apr 03 '17 at 09:06
  • 1
    @demonofthemist There may be better reasons than I can think of, but I would guess that the second example is an example of a [God object](https://en.wikipedia.org/wiki/God_object), which is considered an antipattern. It's better to be aware of what dependencies your controllers need and just include those. If you find yourself including a ton of services in every controller, this may be a sign that you need to factor out some reusable components (e.g. using nested, reusable controllers or directives). – JLRishe Apr 03 '17 at 09:14
  • @demonofthemist no difference in working or behaviour. It's just a workaround to avoid the overhead (_tedious task_) AFAIK – tanmay Apr 03 '17 at 09:14
  • Thanks.. I'll keeping looking more into the working :) – demonofthemist Apr 03 '17 at 11:42