96

I noticed the same question was asked a few times here, I tried so solve it but nothing helps.

I'm following this tutorial with the egghead videos.

But when I get at the section of Controllers and Sharing data between controllers, I can't get it to work.

When I run it with Chrome, I get this error in the console:

'argument 'FirstCtrl' is not a function, got undefined'.

I really don't know what's wrong. The code is the same from in the tutorial.

HTML

<!DOCTYPE html>
<html ng-app>
 <head>
    <title>AngularJS Tutorials: Controllers</title>
    <link rel="stylesheet" href="mystyle.css">
    <script src="http://code.angularjs.org/1.2.0-rc.2/angular.min.js"></script>
 </head>
 <body>
    <div ng-app="">
       <div ng-controller="FirstCtrl">   
           <h1> {{data.message + " world"}}</h1>

           <div class="{{data.message}}">
               Wrap me in a foundation component
           </div>
       </div>
    </div>
    <script type="text/javascript" src="main.js"></script>
 </body>
</html> 

main.js

function FirstCtrl($scope){
   $scope.data = { message: "Hello" };
} 
CroMagnon
  • 1,210
  • 7
  • 20
  • 32
Pumba
  • 971
  • 1
  • 6
  • 5
  • Here is the solution in the second comments - http://stackoverflow.com/questions/24894870/why-is-my-controller-undefined – Kanchan Jul 14 '15 at 09:05

16 Answers16

109

You have 2 unnamed ng-app directives in your html.
Lose the one in your div.

Update
Let's try a different approach.
Define a module in your js file and assign the ng-appdirective to it. After that, define the controller like an ng component, not as a simple function:

<div ng-app="myAppName">  
<!-- or what's the root node of your angular app -->

and the js part:

angular.module('myAppName', [])
    .controller('FirstCtrl', function($scope) {
         $scope.data = {message: 'Hello'};
    });

Here's an online demo that is doing just that : http://jsfiddle.net/FssbL/1/

gion_13
  • 39,371
  • 9
  • 93
  • 105
  • Thanks a lot for the answer, sadly I still get the same error.. So I lost the ng-app="" from the div, but it still doesn't work. – Pumba Oct 16 '13 at 16:02
  • 1
    Thank you so much for your help! I don't understand it anymore, I did the exact same thing like you showed here and in the online demo but it still says 'FirstCtrl' is undefined. I'm going to try it again from the start, hopefully I get it working, because in the next tutorials I get the same problem. – Pumba Oct 17 '13 at 11:28
  • Great!! It works. I forgot to close the type attribute on the script tag for the js file. And that in combination with your second solution made it work! Thank you so much :)) – Pumba Oct 17 '13 at 11:47
  • 6
    The demo video does not wrap controller within the module. So why does it work for him, but not me? https://egghead.io/lessons/angularjs-controllers – Demodave Dec 03 '14 at 20:36
  • 2
    @Demodave, I have the same question. I assume the videos were recorded during an earlier version of AngularJS, and therefore defining controllers was potentially less strict (but, that's just my assumption, I'd be happy for someone to confirm or deny) – MandM Feb 16 '15 at 20:08
  • @MandM, I believe so as well. Anyway I've learned a way around it. – Demodave Feb 17 '15 at 20:19
96

I got exactly the same error message and in my case it turned out i didn't list the controller JS file (e.g. first-ctrl.js) in my index.html

Mariusz
  • 2,419
  • 1
  • 18
  • 25
9

I just did this tutorial and followed @gion_13 answer. Still did not work. Solved it by making my ng-app name in the index identical to the one in my js file. Exactly identical, even the quotes. So:

<div ng-app="myapp">
    <div ng-controller="FirstCtrl">

and the js:

 angular.module("myapp", [])
.controller('FirstCtrl',function($scope) {
    $scope.data= {message:"hello"};
  });

Weird how the ng-app has to be identical but the ng-controller doesn't.

an1waukoni
  • 155
  • 2
  • 12
7

You must name your ng-app, giving your app a namespace; simply using ng-app is not enough.

Instead of:

<html ng-app>
...

You will need something like this instead:

<html ng-app="app">
...

Then, like so:

var app = angular.module("app", []).controller("ActionsController", function($scope){});
user1429980
  • 6,044
  • 2
  • 39
  • 47
6

Another nice one: Accidentally redefining modules. I copy/pasted stuff a little too eagerly earlier today and ended up having a module definition somewhere, that I overrode with my controller definitions:

// controllers.js - dependencies in one place, perfectly fine
angular.module('my.controllers', [/* dependencies */]);

Then in my definitions, I was supposed to reference it like so:

// SomeCtrl.js - grab the module, add the controller
angular.module('my.controllers')
 .controller('SomeCtrl', function() { /* ... */ });

What I did instead, was:

// Do not try this at home!

// SomeCtrl.js
angular.module('my.controllers', []) // <-- redefined module, no harm done yet
  .controller('SomeCtrl', function() { /* ... */ });

// SomeOtherCtrl.js
angular.module('my.controllers', []) // <-- redefined module - SomeCtrl no longer accessible
  .controller('SomeOtherCtrl', function() { /* ... */ });

Note the extra bracket in the call to angular.module.

Michael Jess
  • 1,852
  • 1
  • 18
  • 17
3

remove ng-app="" from

<div ng-app="">

and simply make it

<div>
john smith
  • 531
  • 6
  • 23
  • 3
    If you use routing in the configuration of your app, make sur you don't use ng-controller in the html. You should instead have ng-view. The controller will be usually defined along with the views in the routing. – Marc May 08 '14 at 07:42
1

Me too faced the same issue. But the problem was I forgot to list the module in the list of modules the ng-app depends on.

1

I have faced this issue and it fixed with following way:

  1. first remove ng-app from:

    <html ng-app>
    
  2. add name of ng-app to myApp:

    <div ng-app="myApp">
    
  3. add this line of code before function:

    angular.module('myApp', []).controller('FirstCtrl',FirstCtrl);
    

final look of script:

angular.module('myApp', []).controller('FirstCtrl',FirstCtrl);

function FirstCtrl($scope){
    $scope.data = {message: "Hello"};
} 
Leon Gaban
  • 27,845
  • 80
  • 281
  • 473
Azhar
  • 472
  • 5
  • 16
1

In my case, this message comes from forgotten dependency injection in main module

1

This can happen if you have gulp misconfigured to add your angular app code more than once. In my case, this was in index.js, and it was adding it as part of the directory of js files (globbed in gulp) before and after my controller declarations. Once I added an exclusion for index.js not to be minified and injected the second time, my app began to work. Another tip if any of the solutions above don't address your problem.

rncrtr
  • 2,984
  • 2
  • 20
  • 31
1

Firstly - If the module name is not defined, in the JS you will not be able to access the module and link the controller to it.

You need to provide the module name to angular module. there is a difference in using defining module as well 1. angular.module("firstModule",[]) 2. angular.module("firstModule")

1 - one is to declare the new module "firstModule" with no dependency added in second arguments. 2 - This is to use the "firstModule" which is initialized somewhere else and you're using trying to get the initialized module and make modification to it.

0

i faced this issue but i was able to correct this issue by renaming the controller, please have a try on it.

ctrlSub.execSummaryDocuments = function(){};
Amay Kulkarni
  • 698
  • 9
  • 15
0

sometimes something wrong in the syntax of the code inside the function throws this error. Check your function correctly. In my case it happened when I was trying to assign Json fields with values and was using colon : to make the assignment instead of equal sign = ...

Amitesh Ranjan
  • 904
  • 1
  • 10
  • 9
0

I had two controllers with the same name defined in two different javascript files. Irritating that angular can't give a clearer error message indicating a namespace conflict.

thebiggestlebowski
  • 2,292
  • 1
  • 24
  • 25
0

I am not sure about this tutorial but I had the same problem when I forgot to include the file into grunt/gulp minimization process.

grunt.initConfig({
  uglify: {
    my_target: {
      files: {
        'dest/output.min.js': ['src/input1.js', 'src/missing_controller.js']
      }
    }
  }
});

Hope that helps.

Patrik Bego
  • 3,439
  • 1
  • 23
  • 23
0

Watch your letter casing too. I spent a good hour chasing this bug.

<section id="forgotpwd" ng-controller="ForgotPwdController">

while I name the controller

angular
    .module('app')
    .controller('ForgotpwdController', ForgotpwdController);

They all should be consistently named, in this case ForgotpwdController with lower case p.

Jeson Martajaya
  • 6,291
  • 7
  • 46
  • 52