Search code examples
angularjsrequirejsinstallationdemo

requirejs angular doesn't seem to register controller / services / etc


I have a very simple requirejs and angular demo app. When I run the code, it's as if angular doesn't register the homeController (even tho the file does run and outputs "Hello from home controller"). It's frustrating to get little to no debug info on how to solve this. Any help would be greatly appreciated!

On my local machine, I am getting this error message:

"Error: [ng:areq] Argument 'HomeController' is not a function, got undefined"

On Plnkr I am getting a different message:

Error: [ng:areq]

This is the plnkr link http://plnkr.co/edit/zNVIYckX5dAzV3CpEzXv?p=preview

index.html

  <body ng-app="app">
      <div ng-controller="HomeController">
        {{message}}

    </div>
    <script src="http://requirejs.org/docs/release/2.1.14/minified/require.js" data-main="main.js"></script>
  </body>

main.js

require.config({
    paths: {
        "jquery": '//code.jquery.com/jquery-2.1.1.min',
        "angular": '//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular.min',
        "angular.route": '//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular-route.min'
    },
    shim: {
        "angular": { deps: ["jquery"], exports: "angular" },
        "angular.route": { deps: ["angular"], exports: "angular.route" },
    },
    deps: ["app", "routes"]
});

//kickoff the app
require(["app", "routes" ]);

app.js

define(["angular"], function () {
    $("body").append("hello from app<br/>");
    return angular.module("app", ['ngRoute']);
});

routes.js

define("routes", ["app", "angular.route", "homeController"], function(app) {
    $("body").append("hello from angular.route<br/>");

    app.config(function($routeProvider, $locationProvider) {
        $("body").append("$routeProvider<br/>");
        $locationProvider.html5Mode(true);
        $routeProvider.when("/", {
                templateUrl: "home/home.html",
                controller: "HomeController"
            })

    });
});

homeController.js

define("homeController", ["app"], function (app) {

    $("body").append("hello from home controller<br/>");
    app.controller("HomeController", function ($scope) {
        $("body").append("hello from home controller body<br/>");
        $scope.message = "message from home controller";
    });
});

Solution

  • github demo: https://github.com/zouhenry/angular-requirejs-demo

    I have figured out the problem and hope this answer will help others out there.

    The problem is when dom is ready, angular will parse the html and will try to bind HomeController to the ng-controller directive, even before the homeController file has been loaded by requirejs.

    So what I ended up doing was removing the ng-app directive from index.html. This prevented angular from automatically binding to directives when the page is loaded (we will programmatically bind the application to the page later)

    <body ng-app="app">

    Since I removed ng-app from the Html itself. I need to programmatically bind the the app to html. I did this with in the Main.js

    //kickoff the app
    require(["app", "routes" ], function(){
       angular.bootstrap(document, ["app"]);
    });
    

    Last thing I did was move the require.js to the head instead of the keeping it in the body (not sure if this was necessary). This is the revised index.html

    <html>
      <head>
        <script src="http://requirejs.org/docs/release/2.1.14/minified/require.js" data-main="main.js"></script>
      </head>
      <body>
          <div ng-controller="HomeController">
            {{message}}
        </div>
      </body>
    </html>