121

Using AngularJS with Scala Play, I'm getting this error.

Error: Argument 'MainCtrl' is not a function, got undefined

I'm trying to create a table consisting of the days of the week.

Please take a look at my code. I had checked the name of the Controller, but that seems correct. Note: Code used from this SO answer

index.scala.html

@(message: String)

@main("inTime") {

<!doctype html>
<html lang="en" ng-app>
    <head>
        <link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
    </head>
<div ng-controller="MainCtrl">
    <table border="1">
    <tbody ng-repeat='(what,items) in data'>
      <tr ng-repeat='item in items'>
        <td ngm-if="$first" rowspan="{{items.length}}">{{what}}</td>
        <td>{{item}}</td>
      </tr>
    </tbody>
  </table>
</div>
</html> 
}

MainCtrl.js

(function() {
    angular.module('[myApp]', []).controller('MainCtrl', function($scope) {
        $scope.data = {
            Colors: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
        }
    });
}());
Community
  • 1
  • 1
Kevin Meredith
  • 38,251
  • 58
  • 190
  • 340

17 Answers17

108

Remove the [] from the name ([myApp]) of module

angular.module('myApp', [])

And add ng-app="myApp" to the html and it should work.

Pankaj Parkar
  • 127,691
  • 20
  • 213
  • 279
Chandermani
  • 42,177
  • 11
  • 82
  • 86
  • 1
    All I had to do to get it working was the second suggestion (i.e. set ng-app="myApp"). If I removed the [], I got another error. – Jason Jul 08 '13 at 07:38
  • 15
    Having the second parameter `[]` indicates that you are creating a new module. Removing the second parameter indicates that you are retrieving an existing module. So one possibility to check is if you are calling `angular.module` twice, both times including the second parameter. If so, the later occurrence will overwrite the second, hiding any definitions of controllers up to that point. – Carl G Jul 08 '13 at 22:35
  • 26
    When he says to remove the `[]` he's referring to the first parameter where the OP has `[myApp]` instead of `myApp`. He's not talking about the second parameter. – Kevin Beal Aug 15 '13 at 17:15
  • 1
    Check the name of your controller if you are using routes. The controller name in the route definition is case sensitive. – Latin Warrior Jan 30 '16 at 20:13
78

FIRST. check if you have correct controller in the route definitions, same as the controller names that you are defining

communityMod.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider.
      when('/members', {
        templateUrl: 'modules/community/views/members.html',
        controller: 'CommunityMembersCtrl'
      }).
      otherwise({
        redirectTo: '/members'
      });
  }]);

communityMod.controller('CommunityMembersCtrl', ['$scope',
    function ($scope) {
        $scope.name = 'Hello community';
    }]);

different controller names in this example will lead to errors, but this example is correct

SECOND check if you have imported your javascript file:

<script src="modules/community/controllers/CommunityMembersCtrl.js"></script>

pleerock
  • 16,223
  • 14
  • 93
  • 116
26

I had the same error message (in my case : "Argument 'languageSelectorCtrl' is not a function, got undefined").

After some tedious comparison with Angular seed's code, I found out that I had previously removed a reference to the controllers module in app.js. (spot it at https://github.com/angular/angular-seed/blob/master/app/js/app.js)

So I had this:

angular.module('MyApp', ['MyApp.filters', 'MyApp.services', 'MyApp.directives'])

This failed.

And when I added the missing reference:

angular.module('MyApp', ['MyApp.filters', 'MyApp.services', 'MyApp.controllers', 'MyApp.directives'])

The error message disappeared and Angular could instanciate the controllers again.

bertrand
  • 360
  • 2
  • 6
  • had the same problem, my issue was that I forgot to add my controller to the app module... why does this not happen automatically??? thanks anyhow! – TheZuck Mar 16 '15 at 08:54
16

Some times this error is a result of two ng-app directives specified in the html. In my case by mistake I had specified ng-app in my html tag and ng-app="myApp" in the body tag like this:

<html ng-app>
  <body ng-app="myApp"></body>
</html>
Oliver
  • 8,258
  • 7
  • 64
  • 94
Gaurav
  • 763
  • 8
  • 10
6

This seriously took me 4 HOURS (including endless searches on SO) but finally I found it: by mistake (unintentionally) I added a space somewhere.

Can you spot it?

angular.module('bwshopper.signup').controller('SignupCtrl ', SignupCtrl);

So ... 4 hours later I saw that it should be:

angular.module('bwshopper.signup').controller('SignupCtrl', SignupCtrl);

Almost impossible to see with just the naked eye.

This stresses the vital importance of revision control (git or whatever) and unit/regression testing.

Dehli
  • 5,754
  • 5
  • 27
  • 42
leo
  • 1,001
  • 11
  • 11
  • 1
    My answer was not an extra space but it lead me to my fix. I had `Controller` instead of `controller` and that was all it took. – Grandizer Oct 26 '15 at 21:05
  • And I named my file options-moda.controller.js but was looking for options-modal.controller.js DOH! – theFish Oct 23 '18 at 13:16
  • Mine was because of I forgot to add .js in BundleConfig. Simple but frustrating. – Ege Bayrak Dec 07 '18 at 11:46
4

I have encountered the same problem and in my case it was happening as a result of this problem:

I had the controllers defined in a separate module (called 'myApp.controllers') and injected to the main app module (called 'myApp') like this:

angular.module('myApp', ['myApp.controllers'])

A colleague pushed another controller module in a separate file but with the exact same name as mine (i.e. 'myApp.controllers' ) which caused this error. I think because Angular got confused between those controller modules. However the error message was not very helpful in discovering what is going wrong.

Lilla Eli
  • 231
  • 2
  • 3
  • 1
    This should get fixed by removing the second parameter in the module... To get the existing module using angular.module('myApp') without the second parameter. i.e. angular.module('myApp').contoller(...) – Santhosh Apr 17 '14 at 07:38
3

In my case (having an overview page and an "add" page) I got this with my routing setup like below. It was giving the message for the AddCtrl that could not be injected...

$routeProvider.
  when('/', {
    redirectTo: '/overview'
  }).      
  when('/overview', {
    templateUrl: 'partials/overview.html',
    controller: 'OverviewCtrl'
  }).
  when('/add', {
    templateUrl: 'partials/add.html',
    controller: 'AddCtrl'
  }).
  otherwise({
    redirectTo: '/overview'
  });

Because of the when('/' route all my routes went to the overview and the controller could not be matched on the /add route page rendering. This was confusing because I DID see the add.html template but its controller was nowhere to be found.

Removing the '/'-route when case fixed this issue for me.

EeKay
  • 5,356
  • 3
  • 21
  • 23
  • I was receiving this error as well and tearing my hair out because it was causing my TFS builds to fail. Commenting out the '/' route fixed it for me as well. Now to figure out why! – Phillip Copley Jun 22 '16 at 13:07
3

If you are in a submodule, don't forget to declare the module in main app. ie :

<scrip>
angular.module('mainApp', ['subModule1', 'subModule2']);

angular.module('subModule1')
   .controller('MyController', ['$scope', function($scope) {
      $scope.moduleName = 'subModule1';
   }]);
</script>
...
<div ng-app="mainApp">
   <div ng-controller="MyController">
   <span ng-bind="moduleName"></span>
</div>

If you don't declare subModule1 in mainApp, you will got a "[ng:areq] Argument "MyController" is not a function, got undefined.

syjust
  • 178
  • 1
  • 4
2

Уmed's second point was my pitfall but just for the record, maybe it's helping someone somewhere:

I had the same problem and just before I went nuts I discovered that I had forgotten to include my controller script.

As my app is based on ASP.Net MVC I decided to keep myself sane by inserting the following snippet in my App_Start/BundleConfig.cs

bundles.Add(new ScriptBundle("~/app").Include(
                "~/app/app.js",
                "~/app/controllers/*.js",
                "~/app/services/*.js" ));

and in Layout.cshtml

<head>
...
   @Scripts.Render("~/app")
...
</head>

Now I won't have to think about including the files manually ever again. In hindsight I really should have done this when setting up the project...

Xceno
  • 843
  • 8
  • 21
1

I got sane error with LoginController, which I used in main index.html. I found two ways to resolve:

  1. setting $controllerProvider.allowGlobals(), I found that comment in Angular change-list "this option might be handy for migrating old apps, but please don't use it in new ones!" original comment on Angular

    app.config(['$controllerProvider', function($controllerProvider) { $controllerProvider.allowGlobals(); }]);

  2. wrong contructor of registering controller

before

LoginController.$inject = ['$rootScope', '$scope', '$location'];

now

app.controller('LoginController', ['$rootScope', '$scope', '$location', LoginController]);

'app' come from app.js

var MyApp = {};
var app = angular.module('MyApp ', ['app.services']);
var services = angular.module('app.services', ['ngResource', 'ngCookies', 'ngAnimate', 'ngRoute']);
Dmitri Algazin
  • 3,017
  • 21
  • 25
1

I had the same error with a big mistake:

appFormid.controller('TreeEditStepControlsCtrl', [$scope, function($scope){

}]);

You see ? i forgot the '' around the first $scope, the right syntax is of course:

appFormid.controller('TreeEditStepControlsCtrl', ['$scope', function($scope){

}]);

A first error i didn't see immediatly was: "$scope is not defined", followed by "Error: [ng:areq] Argument 'TreeEditStepControlsCtrl' is not a function, got undefined"

Elo
  • 1,617
  • 17
  • 23
0

Could it be as simple as enclosing your asset in " " and whatever needs quotes on the inside with ' '?

<link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">

becomes

<link rel="stylesheet" media="screen" href="@routes.Assets.at('stylesheets/main.css')">

That could be causing some problems with parsing

0

To fix this problem, I had to discover that I misspelled the name of the controller in the declaration of Angular routes:

.when('/todo',{
            templateUrl: 'partials/todo.html',
            controller: 'TodoCtrl'
        })
MadPhysicist
  • 4,190
  • 7
  • 27
  • 80
0

In my case it was a simple typo in index.html:

<script src="assets/javascript/controllers/questionssIndexController.js"></script>

that should have been

<script src="assets/javascript/controllers/questionsIndexController.js"></script>

without the extra s in the controller's name.

Eddy
  • 3,075
  • 12
  • 48
  • 75
0

Turns out it's the Cache of the browser, using Chrome here. Simply check the "Disable cache" under Inspect (Element) solved my problem.

Weihui Guo
  • 2,600
  • 4
  • 25
  • 45
0

Because this pops-up in Google when trying to find an answer to: "Error: Argument '' is not a function, got undefined".

It's possible that you are trying to create the same module twice.

The angular.module is a global place for creating, registering and retrieving AngularJS modules.

Passing one argument retrieves an existing angular.Module, whereas passing more than one argument creates a new angular.Module

Source: https://docs.angularjs.org/api/ng/function/angular.module#overview

Example:

angular.module('myApp', []) Is used to create a module without injecting any dependencies.

angular.module('myApp') (Without argument) is used to get an existing module.

MCollard
  • 896
  • 2
  • 19
  • 37
0

There appear to be many working solutions suggesting the error has many actual causes.

In my case I hadn't declared the controller in app/index.html:

<scipt src="src/controllers/controller-name.controller.js"></script>

Error gone.

Ty Conway
  • 53
  • 4