1

I have done this when the service and controller are in a single file (usually, app.js) and it works without any issues.

Now, I have the controllers and services organized in different files and the respective folders. I need to inject 1 particular service in a controller but I am running into an error.

This is a simple angular app that I am working on that has a way to manage your YouTube favorite videos. I am getting the error on the add page. Just click on add button to see the error.

Equivalent Plunker

Here is what I have so far:

index.html

<!doctype html>
<html ng-app="youtube-favorites">
    <head>
        <title>My YouTube Favorites</title>
        <link rel="stylesheet" type="text/css" href="bower_components/bootstrap/dist/css/bootstrap.min.css" />
        <link rel="stylesheet" type="text/css" href="css/custom.css" />
    </head>
    <body>
        <div class="container">
            <div class="row">
                <div class="col-md-12" style="border: 1px solid red;">
                    <div ui-view></div>
                </div>
            </div>
        </div>
        <script src="bower_components/angular/angular.js"></script>
        <script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
        <script src="bower_components/angular-ui-router/release/angular-ui-router.min.js"></script>
        <script src="app.js"></script>
        <script src="services/add.js"></script>
        <script src="controllers/home.js"></script>
        <script src="controllers/add.js"></script>
    </body>
</html>

app.js

angular.module('youtube-favorites', ['ui.bootstrap', 'ui.router'])
    .config(['$stateProvider', '$urlRouterProvider',
        function($stateProvider, $urlRouterProvider) {

            // For any unmatched url, redirect to /home
            $urlRouterProvider.otherwise('/home');

            // Now set up the states
            $stateProvider
                .state('home', {
                    url: '/home',
                    templateUrl: 'views/home.html',
                    controller: 'homeController'
                })
                .state('add', {
                    url: '/add',
                    templateUrl: 'views/add.html',
                    controller: 'addController'
                });
        }
    ]);

Controller - add.js

angular.module('youtube-favorites')
    .controller('addController', ['$scope', '$log', 'addService',
        function($scope, $log, addService) {
            $log.info('add');

            $scope.addFavorite = function() {
                addService.addFavorite($scope.title, $scope.youtubeUrl)

                $log.info('title', $scope.title);
                $log.info('youtubeUrl', $scope.youtubeUrl);
            };
        }
    ]);

Service - add.js

angular.module('youtube-favorites', [])
    .service('addService', ['$scope', '$log', '$q', '$window',

        function($scope, $log, $q, $window) {

            $log.info('add service called');

            this.addFavorite = function(title, url) {

                $log.info('title', title);
                $log.info('url', url);

                $window.localStorage.setItem('youtubeFavorites', angular.toJson({
                    title: title,
                    url: url
                }));

                return true;

            };

        }
    ]);

View - add.html

<form name="addForm" ng-submit='addFavorite()' novalidate>
    <div class="form-group">
        <label for="title">Title</label>
        <input type="text" name="title" class="form-control" placeholder="Awesome video!" aria-describedby="title" ng-model="title" required />
        <!-- <p ng-show="addForm.title.$error.required" class="help-block">Please enter the title.</p> -->
    </div>
    <div class="form-group">
        <label for="youtubeUrl">YouTube <em>embed</em> URL</label>
        <input type="text" name="youtubeUrl" class="form-control" placeholder="https://www.youtube.com/embed/someID" aria-describedby="youtubeUrl" ng-model="youtubeUrl" required />
        <!-- <p ng-show="addForm.youtubeUrl.$error.required" class="help-block">Please enter the URL.</p> -->
    </div>
    <div class="form-group">
        <button class="btn btn-default grey" type="submit">Submit</button>
    </div>
</form>

Here is the error that I am getting:

snapshot

Pretty sure that I am not injecting the service correctly.

I did try adding the service as a dependency to the app module as per below, but still giving an error.

angular.module('youtube-favorites', ['ui.bootstrap', 'ui.router', 'youtube-favorites.addService'])....

How do I fix this?

Rahul Desai
  • 15,242
  • 19
  • 83
  • 138

2 Answers2

7

In your addService, change this:

angular.module('youtube-favorites', [])

to this:

angular.module('youtube-favorites')

You are effectively creating a new module with the same name when you include the empty [].

Also, you should be passing in $rootScope to your service because $scope is only available to controllers.

lintmouse
  • 5,079
  • 8
  • 38
  • 54
  • It is still giving me that error. Please see my Plunker: http://plnkr.co/edit/ymoLgiNISsHdDxLBlHYX?p=preview – Rahul Desai Jan 27 '16 at 19:25
  • It worked after I passed `$rootScope` instead of `$scope`. But I am not using `$rootScope` in the service at all. Does this mean that the service gets attached to the `$rootScope`? – Rahul Desai Jan 27 '16 at 20:00
  • 2
    @RahulDesai - Simple, you do not have to pass `$rootScope` to your service(s) so omit that from the dependency and constructor/factory method. – Igor Jan 27 '16 at 20:37
1

You can't inject $scope into a service. You can inject $rootScope, but $scope is a thing that gets injected at the controller level.

Take a look at this stack post for a little more detail.

Community
  • 1
  • 1
bri
  • 2,932
  • 16
  • 17