5

There is something really weird going on when I'm using RequireJS with AngularJS. I managed to load all my angular dependencies through RequireJS. I can see those scripts downloaded when I open up the Sources pane in Chrome's developer tool. But Angular keeps throwing an error in the console that it failed to instantiate the module:

Uncaught Error: [$injector:modulerr] Failed to instantiate module MyTestApp due to:
Error: [$injector:nomod] Module 'MyTestApp' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure...<omitted>...0)

It seems like Angular, when loaded with RequireJS, cannot bind with the ng-app tag in the HTML page. I'm not sure if this is the case but it seems like so to me because when I import angular.min.js manually into the HTML page, it all works fine.

Did I do anything wrong when using RequireJS with Angular? How should I use the two together? Here's how my code look:

index.html

<!doctype html>
<html lang="en" ng-app="MyTestApp">
<head>
  <meta charset="utf-8">
  <title>AngularJS</title>
  <link rel="stylesheet" href="css/style.css"/>
  <script data-main="main" src="js/require.js"></script>
</head>
<body>
  <div ng-controller="TestController">{{helloMessage}}</div>
</body>
</html>

main.js

require.config({
    baseUrl: "scripts/app",

    shim: {
        "angular": {
            exports: "angular"
        },
        "angular.route": {
            deps: ["angular"]
        },
        "bootstrapper": {
            deps: ["angular", "angular.route"]   
        },

    },

    paths: {
        "angular": "../angular",
        "angular.route": "../angular-route",
        "bootstrapper": "bootstrapper"
    }
});

require(["angular", "angular.route", "bootstrapper"],
    (angular, ngRoute, bootstrapper) => {
        bootstrapper.start();
    }
);

bootstrapper.js

function run() {
       app = angular.module("MyTestApp", ["ngRoute"]);
       app.controller("TestController", TestController);
       console.log(app); //Prints object to console correctly, ie, angular was loaded.
}

2 Answers 2

6

Here is how I would do it (DEMO).

In main.js, require angular, your app and maybe a controllers.js and other files:

require(['angular', 'app'], function (app) {
    angular.element(document).ready(function () {
        angular.bootstrap(document, ['MyTestApp']);
    });
});

In app.js, require angular and angular route:

define(['angular', 'angular.route'], function() {
    var app = angular.module("MyTestApp", ["ngRoute"]);

    return app;
});

This is manual bootstraping and therefore does not need the ng-app tag at all.

I'm currently working on a pretty big application with angular and requirejs and I prefer to load the "big" libraries that are used by the whole app anyway independently from requirejs. So I load one big file which includes angular, angular-route, requirejs, main.js in the beginning. Or if it makes sense to use a CDN version, load it from there. On the other hand I load every controller, directive, filter and service on request. I currently have 50+ controllers which allready makes a difference in initial load time.

But that all depends on the size of your app.

Sign up to request clarification or add additional context in comments.

Comments

1

First you does not need to get a variable from the load of "angular.route". The module will be directly loaded in angular.

I think you should also wait for the dom ready event and also make a requirejs app module that will be in charge of loading all app dependencies:

app/app.js:

define([
  "angular",
  "angular-route",
  "app/controllers",
  "app/directives",
  [...]
], function(angular){
  var app = angular.module('app', [
    "ngRoute",
    "app.controllers",
    "app.directives",
    [...]
    ])
    .config([function(){
      // app configuration goes here
    }]);

    return app;
})

main.js

require(["angular", "app/app"],
  function (angular, app){
    angular.element(document).ready(function() {
      angular.bootstrap(document, [app.name]);
    });
  }
);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.