Error: [$injector:nomod] Module '<name_of_module>' is not available - javascript

this is part of my configuration file karma.conf.js:
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '../',
// list of files / patterns to load in the browser
files: [
'app/bower_components/angular/angular.js',
'app/bower_components/angular-route/angular-route.js',
'app/bower_components/angular-mocks/angular-mocks.js',
'app/js/app.js',
'app/js/controllers/*.js',
'app/js/services/*.js',
'test/unit/*.js'
],
and this is my folders struct:
This is app.js file:
/**
* Created by Pietro on 30/12/15.
*/
'use strict';
var drfmApp = angular.module('drfmApp', [
'ngRoute','drfmControllers','ngCookies'
]);
drfmApp.config(['$routeProvider','$locationProvider',
function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'views/login.html',
controller: 'LoginController'
}).
when('/login', {
templateUrl: 'views/login.html',
controller: 'LoginController',
}).
when('/register', {
templateUrl: 'views/register.html',
controller: 'RegisterController',
}).
when('/dashboardESCO', {
templateUrl: 'views/dashboard_esco.html',
controller: 'DashboardESCOControllers'
}).
when('/dashboardRetailer', {
templateUrl: 'views/dashboard_retailer.html',
controller: 'DashboardRetailerControllers'
}).
when('/dashboardAggregator', {
templateUrl: 'views/dashboard_aggregator.html',
controller: 'DashboardAggregatorControllers'
}).
otherwise({
redirectTo: '/login'
});
}]);
drfmApp.run(['$rootScope', '$location', '$cookieStore', '$http',
function($rootScope, $location, $cookieStore, $http) {
// keep user logged in after page refresh
$rootScope.globals = $cookieStore.get('globals') || {};
if ($rootScope.globals.currentUser) {
$http.defaults.headers.common['Authorization'] = 'Basic ' + $rootScope.globals.currentUser.authdata; // jshint ignore:line
}
$rootScope.$on('$locationChangeStart', function (event, next, current) {
// redirect to login page if not logged in and trying to access a restricted page
// $ รจ jQuery
var restrictedPage = $.inArray($location.path(), ['/login', '/register']) === -1;
var loggedIn = $rootScope.globals.currentUser;
if (restrictedPage && !loggedIn) {
console.log('Run Config: User not logge in or trying to access a restricted web page')
$location.path('/login');
}
});
}]);
I'm trying to run a simple unit test file like this (using Karma and Jasmine):
'use strict';
/* jasmine specs for controllers go here */
describe('Drfm controllers', function () {
beforeEach(module('drfmControllers'));
it('DUMMY TEST', function () {
expect(3).toBe(3);
});
});
where drfmApp is the name of the main module in app.js file
This is where drfmControllers is defined (in controllers.js):
/**
* Created by Pietro on 07/01/16.
*/
'use strict';
var drfmControllers = angular.module('drfmControllers', []);
drfmControllers.controller('DashboardESCOControllers', ['$scope',
function($scope) {
$scope.dashboard = "ESCO Dashboard";
}
]);
drfmControllers.controller('DashboardRetailerControllers', ['$scope',
function($scope){
$scope.dashboard="Retailer Dashboard";}
]);
drfmControllers.controller('DashboardAggregatorControllers', ['$scope',
function($scope){
$scope.dashboard="Aggregator Dashboard";}
]);
But I always have this error:
Error: [$injector:nomod] Module 'drfmControllers' 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.
http://errors.angularjs.org/1.4.8/$injector/nomod?p0=drfmControllers at /Users/Pietro/repos/drfmcockpit/app/bower_components/angular/angular.js:68
I read about the order of the *.js files in karma configuration file: but seems it is according to this rule [see "files" at the start of the question].
Thanks to everybody
UPDATE SOLUTION: changing the conf file with this:
// list of files / patterns to load in the browser
files: [
'app/bower_components/angular/angular.js',
'app/bower_components/angular-route/angular-route.js',
'app/bower_components/angular-mocks/angular-mocks.js',
'app/js/app.js',
'app/js/controllers/controllers.js',
'app/js/controllers/LoginController.js',
'app/js/controllers/RegisterController.js',
'test/unit/*.js'
],
It runs well. Seems something in files inspections. I don't know well..

You haven't set basePath in you configuration options. By default, it is equal to ''. In it's turn, empty string as a basePath value, makes it relative to the configuration file directory. It is described here:
If the basePath is a relative path, it gets resolved to the directory
where the configuration file is located
That means that either you should set basePath value to an absolute path, or you should change your files paths to relative, like:
files: [
'../app/bower_components/angular/angular.js',
'../app/bower_components/angular-route/angular-route.js',
'../app/bower_components/angular-mocks/angular-mocks.js',
'../app/js/app.js',
'../app/js/controllers/*.js',
'../app/js/services/*.js',
'unit/*.js'
],

Related

Link module from external file in AngularJS

I'm working on new project and I want to use two modules placed in separated files. Unfortunetaly, when I try to declare second in my root one I receive an error
Uncaught Error: [$injector:modulerr]
So, here is my root file, app.js:
var beerMe = angular.module("beerMe", ["admin", "ngRoute"])
.config(["$routeProvider", function($routeProvider) {
$routeProvider
.when("/home", {
templateUrl: "../views/home/home.html",
controller: "MyCtrl"
})
.otherwise({
redirectTo: "/home"
})
}])
.controller("MyCtrl", ["$scope", function($scope) {
}]);
And second one, which I want to bind, admin.js:
var admin = angular.module("admin", ["firebase", "ngRoute"]);
admin.config(["$routeProvider", function($routeProvider) {
$routeProvider
.when("/", {
templateUrl: "views/add.html",
controller: "AdminCtrl"
}).when ("/edit", {
templateUrl: "views/edit.html",
controller: "AdminCtrl"
}).otherwise({
redirectTo: "/"
})
}]);
admin.controller("AdminCtrl", ["$scope", "$firebaseArray", function($scope, $firebaseArray) {
// my code goes here
}]);
In admin.js I connnect to firebase and I want to have access to all data from my module "beerMe".
I'd be very grateful if you could help me to figure out why there's a problem with binding these two.
Change var admin = angular.module("admin", ["firebase", "ngRoute"]);
to var admin = angular.module("admin");
and change root module like this
var beerMe = angular.module("beerMe", ["admin", "ngRoute", "firebase"])
It looks like your dependencies are the wrong way round. Having admin as a dependency of beerMe will not make the beerMe module available in your admin module.
If you want your admin module to be able to access data from inside the beerMe module then beerMe should be a dependency of admin.
var admin = angular.module('admin', ['firebase', 'ngRoute', 'beerMe']);

Cannot inject ui.bootstrap into my module

I'm trying to inject ui.bootstrap into my module, called 'app'. I already included the ui-bootstrap javascript file into my html, but I get below error no matter what I do:
Uncaught Error: [$injector:modulerr]
If I remove any dependencies to ui.bootstrap, the error goes away.
Order of js imports in head tag, all of which load up fine. (checked in Chrome dev tools)
<script src="/Scripts/angular.min.js"></script>
<script src="/Scripts/angular-route.js"></script>
<script src="/Scripts/angular-ui-router.min.js"></script>
<script src="/Scripts/angular-animate.js"></script>
<script src="/Scripts/ui-bootstrap-tpls-1.2.5.min.js"></script>
Current AngularJS version is 1.5.2
app.js
(function () {
'use strict';
var app = angular.module('app', [
// Angular modules
'ngRoute',
'ngAnimate',
'ui.bootstrap',
// Custom modules
// 3rd Party Modules
'ui.router'
]);
app.config(['$locationProvider', '$stateProvider', '$urlRouterProvider', '$modal', function ($locationProvider, $stateProvider, $urlRouterProvider, $modal) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
controller: 'frontpageController',
templateUrl: 'app/views/frontpage.html',
data: {
authorize: false
}
})
.state('login', {
url: '/login',
controller: 'loginController',
templateUrl: 'app/views/login.html',
data: {
authorize: false
}
})
.state('profile', {
url: '/profile/:userId',
controller: 'profileController',
templateUrl: 'app/views/profile.html',
data: {
authorize: true
}
})
.state('error', {
url: '/error',
controller: 'errorController',
templateUrl: 'app/views/404.html',
data: {
authorize: false
}
})
}]);
app.run(function ($rootScope, loginService) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
var authorize = toState.data.authorize;
if (authorize && typeof $rootScope.currentUser === 'undefined') {
event.preventDefault();
// get me a login modal!
loginService()
}
});
});
})();
You cannot inject services in module config, it only allow providers.
$modal is renamed as $uibModal in last ui-bootstrap too (to rename in your controllers).
So remove '$modal' from your .config inject it only when you use it.
Are you sure ui bootstrap has only one JS file ? Check all folders of ui bootstrap and add if you are missing any other JS files.
You have to add tpls and library for ui bootstrap. For example:
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.2.5/ui-bootstrap-tpls.js"></script>
and
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.2.5/ui-bootstrap.js"></script>
It may be the version of your angular. it says on the site requires AngularJS 1.4.x or higher.

Angular minification with grunt results in 'Failed to instantiate module' error

I am aware of setting up a controller, service, model etc for prepping for minification. I have about 20 controllers, models and services as individual files and I want to minify and concat them all into one JS file for production.
To get an idea of how I have these files setup, here is an example:
VforumJS.controller('MainController', ['$scope', '$location', '$sce', 'MainModel', 'LogModel', 'MainDebug', 'timecode', 'Idle', function($scope, $location, $sce, MainModel, LogModel, MainDebug, timecode, Idle)
{
...
}]);
After minification, I get the error
Failed to instantiate module VforumJS due to:
Error: [$injector:unpr] http://errors.angularjs.org/1.4.1/$injector/unpr?p0=a
If I click the error link, it says Unknown provider: a
Here is where my module gets created
var VforumJsConfig = function($routeProvider, $locationProvider, localStorageServiceProvider)
{
localStorageServiceProvider.setPrefix('vforumdesktop');
$locationProvider.html5Mode(true);
$routeProvider
.when('/', {
...
})
.otherwise({
...
});
};
var VforumJS = angular.module('VforumJS', ['ngRoute','LocalStorageModule', 'ngTouch', 'ui-rangeSlider','base64','ngIdle'])
.config(['$routeProvider', '$locationProvider', 'localStorageServiceProvider', VforumJsConfig])
.constant('LogTypes', {
LOGIN: 1,
IDLE_LOGOUT: 2,
MANUAL_LOGOUT: 3,
VFORUM_OPEN: 4,
VFORUM_CLOSE: 5
})
.constant('SendLogs', false)
.constant('MainDebug', true);
Am I maybe not doing the proper minification prep in the above code where the module is created?
Here is my Gruntfile.js
'use strict';
module.exports = function(grunt)
{
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
all_src: {
options: {
sourceMap: true,
sourceMapName: 'source.map'
},
src: 'resources/js/**/*.js',
dest: 'composite.all.min.js'
}
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['uglify']);
};
Your .config is definitely one of the issues. Double check and make sure that everywhere in your code that you are injecting a service/provider that you are using the in-line minification.
This is what a config injecting one provider (just $logProvider for this example) will look like after minification:
.config(function(a){
console.log("Never gets here, but a is", a);
})
When really it should look like this:
.config(['$logProvider', function(a){
console.log("a is", a);
}])
Here is a codepen: http://codepen.io/troylelandshields/pen/xGjKGV
Your VforumJsConfig line is the issue
var VforumJsConfig = function($routeProvider, $locationProvider, localStorageServiceProvider)
The function parameters get minified, and angular doesn't know where to inject them from. You need to supply them as strings ( just like your other functions ), as strings won't be altered during minification.
From the docs:
https://docs.angularjs.org/tutorial/step_05#a-note-on-minification
So you will need to add after the definition of VforumJsConfig:
VforumJsConfig.$inject = ['$routeProvider', '$locationProvider', 'localStorageServiceProvider']
Use the array syntax for VforumJsConfig so that the dependencies are defined explicitly rather than implied by the parameter names which will be minified. Instead of:
var VforumJsConfig = function($routeProvider, $locationProvider,
localStorageServiceProvider)
{
localStorageServiceProvider.setPrefix('vforumdesktop');
$locationProvider.html5Mode(true);
$routeProvider
.when('/', {
...
})
.otherwise({
...
});
};
Try:
var VforumJsConfig = ['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider, localStorageServiceProvider)
{
localStorageServiceProvider.setPrefix('vforumdesktop');
$locationProvider.html5Mode(true);
$routeProvider
.when('/', {
...
})
.otherwise({
...
});
}];

"Cannot read property 'untilResolved' of undefined" in angular-route-segment?

I am setting up a simple routing configuration with angular-route-segment and Angular is throwing this error on app load:
TypeError: Cannot read property 'untilResolved' of undefined
Neither Angular nor angular-route-segment provide anything more helpful in the way of error messages.
app.js:
(function () {
'use strict';
var app = angular.module('emailHandlerApp', [
// Angular modules
'ngAnimate', // animations
'ngRoute', // routing
'ngSanitize', // sanitizes html bindings (ex: topnav.js)
// 3rd Party Modules
'ui.bootstrap', // ui-bootstrap (ex: carousel, pagination, dialog)
'route-segment', // angular-route-segment
'view-segment', // angular-route-segment
]);
console.log("app loaded"); // just for debug!
})();
config.route.js:
(function () {
'use strict';
var app = angular.module('emailHandlerApp');
// Configure the routes and route resolvers
app.config(function ($routeSegmentProvider, $routeProvider) {
$routeSegmentProvider.options.autoLoadTemplates = true;
$routeSegmentProvider.options.strictMode = true;
$routeSegmentProvider
.when('/', 'emailHandler')
.when('/unsubscribe', 'emailHandler.unsubscribe')
.when('/redirect', 'emailHandler.redirect')
// Base shell
.segment('emailHandle', {
templateUrl: 'app/shell.html',
controller: 'baseController',
controllerAs: 'vm',
})
.within()
// Dashboard
.segment('unsubscribe', {
templateUrl: 'app/unsubscribe/unsubscribe.html',
controller: 'unsubscribeController',
controllerAs: 'vm',
dependencies: ['emailId']
})
// Recruiting
.segment('redirect', {
templateUrl: 'app/redirect/redirect.html',
controller: 'redirectController',
controllerAs: 'vm',
dependencies: ['rdId']
})
;
$routeProvider.otherwise({ redirectTo: '/' });
})
})();
Answering my own question because I'm 99% sure I'll probably Google this again a month from now.
This one is super simple - just a matter of code blindness and a slightly uninformative error message. angular-route-segment throws this when there's a name out of place somewhere in your segment tree.
In my case, I had mistyped .segment('emailHandle', { ... }) when I meant emailHandler, and then it barfed once it hit the .within(). I felt pretty dumb once I saw it.

Using ocLazyLoad to lazy load a controller with $stateProvider

I'm having issues using oclazyload with $stateProvider.
I have specified that the controller .js should be loaded in the router config, and it does,' but it's not available to use as an ng-controller attribute in the file loaded in templateURL.
ui-route config:
core
.run(
[ '$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}
]
)
.config(
[ '$stateProvider', '$urlRouterProvider',
function ($stateProvider, $urlRouterProvider) {
console.info('Routing ...');
$urlRouterProvider
.otherwise('/app/dashboard');
$stateProvider
.state('app', {
abstract: true,
url: '/app',
templateUrl: 'templates/app.html',
})
.state('app.orders', {
abstract: true,
url: '/orders',
templateUrl: 'templates/orders/orders.html',
})
.state('app.orders.index', {
url: '/index',
templateUrl: 'templates/orders/index.html',
resolve: {
deps: ['$ocLazyLoad',
function( $ocLazyLoad ){
console.info('Path ot order controller in route config',Momento.paths.js + 'controllers/orders/index.js');
return $ocLazyLoad.load([
Momento.paths.js + 'controllers/orders/index.js'
])
}
]
}
})
}
]
)
;
And my templateURL file starts:
<div class="" id="" ng-controller="OrdersIndexController">...</div>
But when it loads, console throws the error:
<info>orders/index controller loaded controllers/orders/index.js:3
<info>Now I've finished loading the controller/order/index.js config/ui-router.js:69
<info>orders template loaded VM30437:1 (<-- this is the app.orders abstract template with ui-view directive ready for app.orders.index view)
<error>Error: [ng:areq] Argument 'OrdersIndexController' is not a function, got undefined
... <trace>
So the file is loaded correctly by lazyload, confirmed by console output above and network tab in developer tools, but it's not available in the templateURL to use as controller? Does it need to be aliased either in router config using controller:'' key or in template? Does it need to be specifically attached to the (only) module in this app?
What am I missing?
PS: confirming that the name of the controller is in fact OrdersIndexController:
core
.controller('OrdersIndexController', [
'Model', '$scope', '$window',
function( Model, $scope, $window){
console.info("OrdersIndexController fired");
}
]);
You have to register your controller with
angular.module("myApp").controller
Working
angular.module("myApp").controller('HomePageController', ['$scope', function ($scope) {
console.log("HomePageController loaded");
}]);
Not working
var myApp = angular.module("myApp")
myApp.controller('HomePageController', ['$scope', function ($scope) {
console.log("HomePageController loaded");
}]);
Inside the function function($ocLazyLoad){} you must to declare the name of module that contains the controller and the name of file "to lazy load"
function( $ocLazyLoad ){
return $ocLazyLoad.load(
{
name: 'module.name',
files: ['files']
}
);
}
If you use the current documented way for ocLazyLoad 1.0 -> With your router
...
resolve: { // Any property in resolve should return a promise and is executed before the view is loaded
loadMyCtrl: ['$ocLazyLoad', function($ocLazyLoad) {
// you can lazy load files for an existing module
return $ocLazyLoad.load('js/AppCtrl.js');
}]
}
then in js/AppCtrl.js
You have something like this:
angular.module("myApp").controller('DynamicNew1Ctrl', ['$scope', function($scope) {
$scope.name = "Scoped variable";
console.log("Controller Initialized");
}]);
Note that with angular.module("myApp") you are attaching the new controller to an existing module, in this case the mainApp, so any of new dynamic controllers can use the app dependencies.
but you can define a new module an inject your dependencies, as described here, the later is used commonly when you estructure your app with a plugin architecture and you want to isolate the dynamic modules so they only have access to some especific dependencies

Categories