Search code examples
javascriptangularjsrequirejsangular-amd

Require.js + AngularAMD - Error: [ng:areq] Argument 'loginController' is not a function, got undefined


I have looked through all the similar questions I can find but none was helpful in resolving this error:

Error: [ng:areq] Argument 'loginController' is not a function, got undefined.

Below are my files:

LoginController.js

"use strict";
    define(['app-config', 'loginService'], function (app) {
    app.controller('LoginController', ['$scope', '$location', 'loginService',
        function (sc, loc, loginService) {

            sc.login = function () {

              console.log("Email Address = " + sc.EmailAddress);
              console.log("Password = " + sc.Password);
            }

    }]);

app-config.js

"use strict";
define(['angularAMD', 'angular-route', 'angular-resource'], function (angularAMD) {
var app = angular.module("openInterviewApp", ['ngRoute', 'ngResource']);

app.config(['$routeProvider',
    function($routeProvider) {
        $routeProvider
           /* .when('/login', angularAMD.route({

                templateUrl: 'Accounts/Login.html',
                controllerUrl: 'Accounts/LoginController'
            })) */
            .when("/:section/:tree", angularAMD.route({

                templateUrl: function (rp) { return rp.section + '/' + rp.tree + '.html'; },

                resolve: {

                    load: ['$q', '$rootScope', '$location', function ($q, $rootScope, $location) {

                        var path = $location.path();
                        var parsePath = path.split("/");
                        var parentPath = parsePath[1];
                        var controllerName = parsePath[2];

                        var loadController = parentPath + "/" + controllerName + "Controller";
                        console.log ("loadController=" + loadController);

                        var deferred = $q.defer();
                        require([loadController], function () {
                            $rootScope.$apply(function () {
                                deferred.resolve();
                            });
                        });
                        return deferred.promise;
                    }]
                }

            }))
            .otherwise({ redirectTo: '/' });

    }]);

angularAMD.bootstrap(app);

return app;
});

main.js

require.config({

//By default load any module IDs from baseUrl
//baseUrl is normally set to the same directory as the script used in a data-main attribute
baseUrl: "",

// paths config is relative to the baseUrl
// never includes a ".js" extension since the paths config could be for a directory.
// ex: app: 'app' means if the module ID starts with "app", load it from the /app directory
paths: {
    'app-config': 'scripts/app-config',
    'angular': 'scripts/angular-1.3.15',
    'angular-route': 'scripts/angular-route-1.3.15',
    'angular-resource': 'scripts/angular-resource-1.3.15',
    'angularAMD': 'scripts/angularAMD-4.13.2015',
    'jquery': 'scripts/jquery-2.1.3.min',
    'loginService': 'services/loginService'
},

// Add angular modules that does not support AMD out of the box, put it in a shim
shim: {
    'angularAMD': ['angular'],
    'angular-route': ['angular'],    //angular-route depends on angular module
    'angular-resource': ['angular']
},

// kick start application
deps: ['app-config']
});

Login.html

<div class="container" ng-controller="LoginController" ng-cloak>

loginService.js

define(['app-config'], function (app) {

app.factory('loginService', ['$resource',
function ($resource) {
    return $resource(
        'jbossews-1.0/login',
        {}, {
        login: { method: 'POST', cache: false, isArray: false }
    });
}]);
});

Solution

  • Your controller should like this,Try this

    "use strict";
    define(['app-config', 'loginService'], function (app) {
        app.register.controller('LoginController', ['$scope', '$location', 'loginService',
            function (sc, loc, loginService) {
                console.log("LoginController calling");
                sc.login = function () {
                    console.log("Email Address = " + sc.EmailAddress);
                    console.log("Password = " + sc.Password);
                };
            }]);
    });
    

    and loginService.js should be like this

    define(['app-config'], function (app) {
    
    app.register.factory('loginService', ['$resource',
      function ($resource) {
          return $resource(
              'jbossews-1.0/login',
              {}, {
              login: { method: 'POST', cache: false, isArray: false }
          });
      }]);
    });
    

    Note: This is something which you are missing, Let me try to explain here in more detail.(Considering you have a basic knowledge of require and angularAMD)

    Controllers and services in the application rely on RequireJS to access the object representing the application’s module and then access the register property to register a controller script with AngularJS.

    This type of registration is required since using the standard angular.module(“ModuleName”).controller() code won’t work properly with dynamically loaded controller scripts.

    RequireJS’s define() function to get to the app object and then uses it to register the controller.

    The app.register.controller() function points to AngularJS’s $controllerProvider.register() function behind the scenes with app.js.

    All of the controllers,services in the application follow this pattern.