leo_roar_001 leo_roar_001 - 3 months ago 32
AngularJS Question

RequireJS shim config for ngRoute and Underscore.js

I am trying to load the dependencies for various angular modules using require.js. After configuring the dependencies in dependencies.js file, I get an error while loading the application which states "Module not available". I tried 2 variations of the file given below and the application fails on both the instances :

Variation 1 - Dependencies.js

require.config({
paths: {
angular: '../lib/dependencies/bower_components/angular/angular',
angularRoute: '../lib/dependencies/bower_components/angular-route/angular-route',
angularMessages: '../lib/dependencies/bower_components/angular-messages/angular-messages',
lodash: "../lib/dependencies/bower_components/lodash/dist/lodash",
jQuery: "../script/datetimepicker/jquery.min", // needed only by the date time picker
datetimepicker: '../script/datetimepicker/jquery.datetimepicker',
underscore: '../lib/dependencies/bower_components/underscore/underscore',
frontendServices: 'frontend-services',
myApp: "test-app"
},
shim: {
jQuery: {
exports: "jQuery"
},
angular: {
exports: "angular"
},
angularRoute: {
exports: "ngRoute"
},
angularRoute: {
deps: ['angular']
},
underscore: {
exports: "_"
},
underscore: {
deps: ['jQuery']
},
datetimepicker: {
deps: ['jQuery']
},
angularMessages: {
deps: ['angular']
},
frontendServices: {
deps: ['angular', 'lodash']
},
myApp: {
deps: [ 'lodash', 'angular', 'angularMessages', 'frontendServices', 'underscore']
}
}
});

require(['myApp'], function () {

angular.bootstrap(document.getElementById('myApp'), ['myApp']);

});


Variation 2 - Dependencies.js

require.config({
paths: {
angular: '../lib/dependencies/bower_components/angular/angular',
angularRoute: '../lib/dependencies/bower_components/angular-route/angular-route',
angularMessages: '../lib/dependencies/bower_components/angular-messages/angular-messages',
lodash: "../lib/dependencies/bower_components/lodash/dist/lodash",
jQuery: "../script/datetimepicker/jquery.min", // needed only by the date time picker
datetimepicker: '../script/datetimepicker/jquery.datetimepicker',
underscore: '../lib/dependencies/bower_components/underscore/underscore',
frontendServices: 'frontend-services',
myApp: "test-app"
},
shim: {
jQuery: {
exports: "jQuery"
},
angular: {
exports: "angular"
},
angularRoute: {
exports: "ngRoute"
},
angularRoute: {
deps: ['angular']
},
underscore: {
deps: ['jQuery']
},
datetimepicker: {
deps: ['jQuery']
},
angularMessages: {
deps: ['angular']
},
frontendServices: {
deps: ['angular', 'lodash']
},
myApp: {
deps: [ 'lodash', 'angular', 'angularMessages', 'frontendServices', 'underscore']
}
}});

require(['myApp'], function () {

angular.bootstrap(document.getElementById('myApp'), ['myApp']);

});


My controller file :

angular.module('myApp', [ 'frontendServices', 'underscore', 'angularRoute']).controller(
'TableCtrl',
[ '$http',
'$scope',
function($scope, $timeout) {

// contents

} ]);


After loading the application I get the errors like :

Error: [$injector:nomod] Module 'underscore' 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.3.8/$injector/nomod?p0=underscore





Can anybody help provide me the correct way to configure underscore and ngRoute using require.js????

Answer

There are multiple problems with your code:

  1. Unless you are using ancient versions of jQuery, jQuery does not need a shim. Same for Underscore.

  2. you must refer to jQuery as a module in all lower case: jquery. It still exports jQuery in the global space but the module name (which you put in dependency lists passed to require or define) must be all lower case.

  3. You cannot duplicate entries in shim. You have this for instance:

    angularRoute: {
        exports: "ngRoute"
    },
    angularRoute: {
      deps: ['angular']
    },
    

    Only the 2nd one will be in effect, the 1st one will be ignored. Merge the two entries into one that has both exports and deps.

  4. It looks like you are trying to get Angular to load RequireJS modules with angular.module('myApp', [ 'frontendServices', 'underscore', ...

    I don't see how that would work. A RequireJS module is not automatically an Angular module. If a RequireJS module contains an Angular module, then you have to get RequireJS to load the module first.

    The todomvc example contains a good example of this:

    require([
        'controllers/todo', 
        'directives/todoFocus', 
        'directives/todoEscape',
        'services/todoStorage'
    ], function (todoCtrl, todoFocusDir, todoEscapeDir, todoStorageSrv) {
        angular
            .module('todomvc', [todoFocusDir, todoEscapeDir, todoStorageSrv])
            .controller('TodoController', todoCtrl);
        angular.bootstrap(document, ['todomvc']);           
    }); 
    

    They load the modules through a require call and then pass them to angular.module. They decided to use require due to how they organized their code. Putting the dependencies in the dependency list passed the top level define of a module would do just as well.

Comments