osumatu osumatu - 5 months ago 106
AngularJS Question

Failed to instantiate module starter due

I keep getting that error and i have no idea why:


Error: [$injector:modulerr] Failed to instantiate module starter due
to: [$injector:modulerr] Failed to instantiate module
starter.controllers due to: [$injector:modulerr] Failed to instantiate
module starter.services due to: [$injector:nomod] Module
'starter.services' is not available! You either misspelled the module
name or forgot to load it. If registering a module ensure that you
specify the dependencies as the second argument.


calendar.html file:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<script src="lib/ionic/js/ionic.bundle.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<script src="cordova.js"></script>
<!-- your app's js -->
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>
</head>
<body ng-app="starter">
<ion-pane ng-controller="CalendarCtrl">
<ion-content>

<div class="card" ng-repeat="event in events">
<div class="item item-divider">
{{event.title}}
</div>
<div class="item item-text-wrap">
{{ event.description }}
<p/>
<strong>When: {{ event.date | date:'short' }}</strong>
</div>
</div>

</ion-content>
</ion-pane>
</body>
</html>


services.js file:

angular.module('starter.services', [])

.factory('Events', function($q) {

var incrementDate = function (date, amount) {
var tmpDate = new Date(date);
tmpDate.setDate(tmpDate.getDate() + amount)
return tmpDate;
};

//create fake events, but make it dynamic so they are in the next week
var fakeEvents = [];
fakeEvents.push(
{
"title":"Meetup on Ionic",
"description":"We'll talk about beer, not Ionic.",
"date":incrementDate(new Date(), 1)
}
);
fakeEvents.push(
{
"title":"Meetup on Beer",
"description":"We'll talk about Ionic, not Beer.",
"date":incrementDate(new Date(), 2)
}
);
fakeEvents.push(
{
"title":"Ray's Birthday Bash",
"description":"Celebrate the awesomeness of Ray",
"date":incrementDate(new Date(), 4)
}
);
fakeEvents.push(
{
"title":"Code Review",
"description":"Let's tear apart Ray's code.",
"date":incrementDate(new Date(), 5)
}
);

var getEvents = function() {
var deferred = $q.defer();
deferred.resolve(fakeEvents);
return deferred.promise;
}

return {
get:getEvents
};

});


controller.js file:

angular.module('starter.controllers', ['starter.services'])

.controller('AppCtrl', function ($scope, $ionicModal, $timeout) {

// With the new view caching in Ionic, Controllers are only called
// when they are recreated or on app start, instead of every page change.
// To listen for when this page is active (for example, to refresh data),
// listen for the $ionicView.enter event:
//$scope.$on('$ionicView.enter', function(e) {
//});

// Form data for the login modal
$scope.loginData = {};

// Create the login modal that we will use later
$ionicModal.fromTemplateUrl('templates/login.html', {
scope: $scope
}).then(function (modal) {
$scope.modal = modal;
});

// Triggered in the login modal to close it
$scope.closeLogin = function () {
$scope.modal.hide();
};

// Open the login modal
$scope.login = function () {
$scope.modal.show();
};

// Perform the login action when the user submits the login form
$scope.doLogin = function () {
console.log('Doing login', $scope.loginData);
// Simulate a login delay. Remove this and replace with your login
// code if using a login system
$timeout(function () {
$scope.closeLogin();
}, 1000);
};
})


.controller('CalendarCtrl', ['starter.services', function ($scope, Events) {

Events.get().then(function (events) {
console.log("events", events);
$scope.events = events;
})
}])

.controller('PlaylistsCtrl', function ($scope) {
$scope.playlists = [
{title: 'Reggae', id: 1},
{title: 'Chill', id: 2},
{title: 'Dubstep', id: 3},
{title: 'Indie', id: 4},
{title: 'Rap', id: 5},
{title: 'Cowbell', id: 6}
];
})


.controller('PlaylistCtrl', function ($scope, $stateParams) {
});


app.js file:

// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'starter.controllers','starter.services'])

.run(function ($ionicPlatform) {
$ionicPlatform.ready(function () {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);

}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})

.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider

.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/menu.html',
controller: 'AppCtrl'
})

.state('app.search', {
url: '/search',
views: {
'menuContent': {
templateUrl: 'templates/search.html'
}
}
})

.state('app.browse', {
url: '/browse',
views: {
'menuContent': {
templateUrl: 'templates/browse.html'
}
}
})

.state('app.calendar', {
url: '/calendar',
views: {
'menuContent': {
templateUrl: 'templates/calendar.html',
controller: 'CalendarCtrl'
}
}
})

.state('app.playlists', {
url: '/playlists',
views: {
'menuContent': {
templateUrl: 'templates/playlists.html',
controller: 'PlaylistsCtrl'
}
}
})

.state('app.single', {
url: '/playlists/:playlistId',
views: {
'menuContent': {
templateUrl: 'templates/playlist.html',
controller: 'PlaylistCtrl'
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/app/playlists');
});

Answer

Firstly, you jinxed your calendar.html with index.html. I recommend you to separate your index.html and calendar.html.

Your starter.controllers injection in app.js was throwing error because of that.

Secondly, after you have injected the starter.services in app.js, you don't need to inject it in every controller file you create although it will not throw error.

Thirdly, your injection of starter.services factory into the controller is just wrong in this case. Your code for services.js is fine though. I have changed the app.js to point to the calendar page directly at first.

Follow the below and you are good to go:

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title></title>

    <link href="lib/ionic/css/ionic.css" rel="stylesheet">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">

    <link href="css/style.css" rel="stylesheet">

    <!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
    <link href="css/ionic.app.css" rel="stylesheet">
    -->

    <!-- ionic/angularjs js -->
    <script src="lib/ionic/js/ionic.bundle.js"></script>

    <!-- cordova script (this will be a 404 during development) -->
    <script src="cordova.js"></script>

    <!-- your app's js -->
    <script src="js/app.js"></script>
    <script src="js/controllers/controllers.js"></script>
    <script src="js/services.js"></script>
  </head>

  <body ng-app="starter">
    <ion-nav-view></ion-nav-view>
  </body>
</html>

calendar.html

<ion-pane ng-controller="CalendarCtrl">
    <ion-content>

        <div class="card" ng-repeat="event in events">
            <div class="item item-divider">
                {{event.title}}
            </div>
            <div class="item item-text-wrap">
                {{ event.description }}
                <p/>
                <strong>When: {{ event.date | date:'short' }}</strong>
            </div>
        </div>

    </ion-content>
</ion-pane>

controller.js

angular.module('starter.controllers', [])

.controller('AppCtrl', function ($scope, $ionicModal, $timeout) {

    // With the new view caching in Ionic, Controllers are only called
    // when they are recreated or on app start, instead of every page change.
    // To listen for when this page is active (for example, to refresh data),
    // listen for the $ionicView.enter event:
    //$scope.$on('$ionicView.enter', function(e) {
    //});

    // Form data for the login modal
    $scope.loginData = {};

    // Create the login modal that we will use later
    $ionicModal.fromTemplateUrl('templates/login.html', {
        scope: $scope
    }).then(function (modal) {
        $scope.modal = modal;
    });

    // Triggered in the login modal to close it
    $scope.closeLogin = function () {
        $scope.modal.hide();
    };

    // Open the login modal
    $scope.login = function () {
        $scope.modal.show();
    };

    // Perform the login action when the user submits the login form
    $scope.doLogin = function () {
        console.log('Doing login', $scope.loginData);
        // Simulate a login delay. Remove this and replace with your login
        // code if using a login system
        $timeout(function () {
            $scope.closeLogin();
        }, 1000);
    };
})


.controller('CalendarCtrl', function ($scope, Events) {

    Events.get().then(function (events) {
        console.log("events", events);
        $scope.events = events;
    })
})

.controller('PlaylistsCtrl', function ($scope) {
    $scope.playlists = [
        {title: 'Reggae', id: 1},
        {title: 'Chill', id: 2},
        {title: 'Dubstep', id: 3},
        {title: 'Indie', id: 4},
        {title: 'Rap', id: 5},
        {title: 'Cowbell', id: 6}
    ];
})


.controller('PlaylistCtrl', function ($scope, $stateParams) {
});  

app.js

// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'starter.controllers','starter.services'])

    .run(function ($ionicPlatform) {
        $ionicPlatform.ready(function () {
            // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
            // for form inputs)
            if (window.cordova && window.cordova.plugins.Keyboard) {
                cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
                cordova.plugins.Keyboard.disableScroll(true);

            }
            if (window.StatusBar) {
                // org.apache.cordova.statusbar required
                StatusBar.styleDefault();
            }
        });
    })

    .config(function ($stateProvider, $urlRouterProvider) {
        $stateProvider

            .state('app', {
                url: '/app',
                abstract: true,
                templateUrl: 'templates/menu.html',
                controller: 'AppCtrl'
            })

            .state('app.search', {
                url: '/search',
                views: {
                    'menuContent': {
                        templateUrl: 'templates/search.html'
                    }
                }
            })

            .state('app.browse', {
                url: '/browse',
                views: {
                    'menuContent': {
                        templateUrl: 'templates/browse.html'
                    }
                }
            })

            .state('app.calendar', {
                url: '/calendar',
                views: {
                    'menuContent': {
                        templateUrl: 'templates/calendar.html',
                        controller: 'CalendarCtrl'
                    }
                }
            })

            .state('app.playlists', {
                url: '/playlists',
                views: {
                    'menuContent': {
                        templateUrl: 'templates/playlists.html',
                        controller: 'PlaylistsCtrl'
                    }
                }
            })

            .state('app.single', {
                url: '/playlists/:playlistId',
                views: {
                    'menuContent': {
                        templateUrl: 'templates/playlist.html',
                        controller: 'PlaylistCtrl'
                    }
                }
            });
        // if none of the above states are matched, use this as the fallback
        $urlRouterProvider.otherwise('/app/calendar');
    });