【问题标题】:Controller not a function, got undefined, while defining controllers globally控制器不是函数,未定义,同时全局定义控制器
【发布时间】:2014-09-26 12:32:26
【问题描述】:

我正在使用 angularjs 编写一个示例应用程序。我在 chrome 浏览器上遇到了下面提到的错误。

错误是

错误:[ng:areq] http://errors.angularjs.org/1.3.0-beta.17/ng/areq?p0=ContactController&p1=not%20a%20function%2C%20got%20undefined

呈现为

参数“ContactController”不是函数,未定义

代码

<!DOCTYPE html>
<html ng-app>
<head>
    <script src="../angular.min.js"></script>
    <script type="text/javascript">
        function ContactController($scope) {
            $scope.contacts = ["abcd@gmail.com", "abcd@yahoo.co.in"];

            $scope.add = function() {
                $scope.contacts.push($scope.newcontact);
                $scope.newcontact = "";                 
            };
        }    
    </script>    
</head>

<body>    
    <h1>  modules sample </h1>

    <div ng-controller="ContactController">
        Email:<input type="text" ng-model="newcontact">
        <button ng-click="add()">Add</button>

        <h2> Contacts </h2>
        <ul>
            <li ng-repeat="contact in contacts"> {{contact}} </li>
        </ul>    
    </div>
</body> 
</html>

【问题讨论】:

    标签: javascript angularjs angularjs-directive angularjs-scope


    【解决方案1】:

    使用 Angular 1.3+,您不能再在全局范围内使用全局控制器声明(无需显式注册)。您需要使用module.controller 语法注册控制器。

    例子:-

    angular.module('app', [])
        .controller('ContactController', ['$scope', function ContactController($scope) {
            $scope.contacts = ["abcd@gmail.com", "abcd@yahoo.co.in"];
    
            $scope.add = function() {
                $scope.contacts.push($scope.newcontact);
                $scope.newcontact = "";
    
            };
        }]);
    

    function ContactController($scope) {
        $scope.contacts = ["abcd@gmail.com", "abcd@yahoo.co.in"];
    
        $scope.add = function() {
            $scope.contacts.push($scope.newcontact);
            $scope.newcontact = "";
        };
    }
    ContactController.$inject = ['$scope'];
    angular.module('app', []).controller('ContactController', ContactController);
    

    这是一个突破性的变化,但它can be turned off to use globals by using allowGlobals

    例子:-

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

    这是来自 Angular 来源的评论:-

    • 检查具有给定名称的控制器是否通过$controllerProvider注册
    • 检查在当前范围内评估字符串是否返回构造函数
    • 如果 $controllerProvider#allowGlobals,请检查全局 window 对象上的 window[constructor](不推荐)
     .....
    
    expression = controllers.hasOwnProperty(constructor)
                ? controllers[constructor]
                : getter(locals.$scope, constructor, true) ||
                    (globals ? getter($window, constructor, true) : undefined);
    

    一些额外的检查:-

    • 请确保将 appname 也放入角根元素的 ng-app 指令中(例如:- html)。示例:- ng-app="myApp"

    • 如果一切正常,但您仍然遇到问题,请记住确保脚本中包含正确的文件。

    • 您没有在不同的地方定义相同的模块两次,这会导致之前在相同模块上定义的任何实体被清除,例如 angular.module('app',[]).controller(.. 和另一个地方 angular.module('app',[]).service(.. (使用两个脚本当然包括在内)可能会导致模块app 上先前注册的控制器在模块的第二次重新创建时被清除。

    【讨论】:

    • 如何按照建议进行检查?检查具有给定名称的控制器是否通过 $controllerProvider 注册
    • app.register.controller('TheController', TheController);对我有用。
    【解决方案2】:

    我遇到了这个问题,因为我在闭包中包装了一个控制器定义文件:

    (function() {
       ...stuff...
    });
    

    但我忘记了实际调用该闭包来执行该定义代码并实际告诉 Javascript 我的控制器存在。即,以上需要是:

    (function() {
       ...stuff...
    })();
    

    注意末尾的 ()。

    【讨论】:

    • +1 有趣的是,视觉工作室似乎有时会自动删除调用。我复制了一个包含此代码的现有 js 文件;原始文件有调用,复制的文件没有。
    【解决方案3】:

    我是 Angular 的初学者,我犯了一个基本错误,即在 Angular 根元素中不包含应用程序名称。因此,将代码从

    <html data-ng-app> 
    

    <html data-ng-app="myApp"> 
    

    为我工作。 @PSL,在上面的回答中已经涵盖了这一点。

    【讨论】:

      【解决方案4】:

      我遇到这个错误是因为我不明白angular.module('myApp', [])angular.module('myApp') 之间的区别。

      创建模块“myApp”并覆盖任何现有的名为“myApp”的模块:

      angular.module('myApp', [])

      检索现有模块“myApp”:

      angular.module('myApp')

      我一直在覆盖另一个文件中的模块,使用上面的第一个调用创建了另一个模块,而不是像我预期的那样检索。

      更多详情:https://docs.angularjs.org/guide/module

      【讨论】:

      • 在我的情况下,我添加了模块,我添加了控制器,但我忘记在应用程序的模块列表中添加模块。 ` angular.module("app", [HEREYOURMODULE] ...`
      【解决方案5】:

      我刚刚迁移到 Angular 1.3.3,我发现如果我在应用程序被覆盖时在不同的文件中有多个控制器并且我丢失了第一个声明的容器。

      我不知道这是否是一个好习惯,但也许对另一个人有帮助。

      var app = app;
      if(!app) {
          app = angular.module('web', ['ui.bootstrap']);
      }
      app.controller('SearchCtrl', SearchCtrl);
      

      【讨论】:

        【解决方案6】:

        我不小心重新声明myApp时遇到了这个问题:

        var myApp = angular.module('myApp',[...]);
        myApp.controller('Controller1', ...);
        
        var myApp = angular.module('myApp',[...]);
        myApp.controller('Controller2', ...);
        

        重新声明后,Controller1 停止工作并引发 OP 错误。

        【讨论】:

          【解决方案7】:

          真的很棒的建议,除了 SAME 错误可能只是因为缺少包含在您的根页面上的关键脚本而发生

          示例:

          页面:index.html

             np-app="saleApp"
          

          缺失

          <script src="./ordersController.js"></script>
          

          当 Route 被告知要提供什么控制器和视图时:

           .when('/orders/:customerId', {
               controller: 'OrdersController',
               templateUrl: 'views/orders.html'
           })
          

          在这个甚至没有引用控制器的意外错误中可能会发生未定义的控制器问题!

          【讨论】:

            【解决方案8】:

            当您有一个包含许多模块的大型项目时,也可能会发生此错误。 确保 Angular 文件中使用的应用程序(模块)与您在模板中使用的应用程序(模块)相同,在本例中为“thisApp”。

            app.js

            angular
            .module('thisApp', [])
                .controller('ContactController', ['$scope', function ContactController($scope) {
                    $scope.contacts = ["abcd@gmail.com", "abcd@yahoo.co.in"];
            
                    $scope.add = function() {
                        $scope.contacts.push($scope.newcontact);
                        $scope.newcontact = "";
            
                    };
                }]);
            

            index.html

              <html>
                <body ng-app='thisApp' ng-controller='ContactController>
                     ...
                    <script type="text/javascript" src="assets/js/angular.js"></script>
                    <script src="app.js"></script>
                </body>
                </html>
            

            【讨论】:

              【解决方案9】:

              如果所有其他方法都失败了,并且您正在使用 Gulp 或类似的东西......只需重新运行它!

              我浪费了 30 分钟四次检查所有东西,而我只需要快速踢裤子。

              【讨论】:

                【解决方案10】:

                如果您正在使用路由(高概率)并且您的配置引用了未声明为依赖项的模块中的控制器,那么初始化也可能会失败。

                例如,假设您已经为您的应用配置了 ngRoute,例如

                angular.module('yourModule',['ngRoute'])
                .config(function($routeProvider, $httpProvider) { ... });
                

                在声明路由的块中要小心,

                .when('/resourcePath', { 
                templateUrl: 'resource.html',
                controller: 'secondModuleController' //lives in secondModule
                });
                

                在“ngRoute”之后将secondModule 声明为依赖项应该可以解决问题。我知道我有这个问题。

                【讨论】:

                  【解决方案11】:

                  我收到此错误是因为我使用了与我的代码不兼容的旧版 Angular。

                  【讨论】:

                    【解决方案12】:

                    在我的例子中,这些错误发生在 list.find() 函数中的语法错误之前; IE11 无法识别列表的“查找”方法,因此必须替换为适用于 IE11 和 chrome 的过滤器方法。 参考https://github.com/flrs/visavail/issues/19

                    【讨论】:

                      【解决方案13】:

                      在我的情况下,此错误之前是 IE11 中列表的查找方法的语法错误。所以按照建议https://github.com/flrs/visavail/issues/19将find方法替换为filter方法

                      然后上述控制器未定义错误已解决。

                      【讨论】:

                        【解决方案14】:

                        我在使用(不够老)AngularJS 1.4.3 的旧教程时遇到了同样的错误。到目前为止,最简单的解决方案是从

                        编辑 angular.js 源代码
                        function $ControllerProvider() {
                          var controllers = {},
                              globals = false;
                        

                        function $ControllerProvider() {
                          var controllers = {},
                              globals = true;
                        

                        并按原样按照教程进行操作,已弃用的全局函数仅用作控制器。

                        【讨论】:

                        • 这是不好的做法。正如 PSL 的回答中提到的,您可以这样做:angular.module('app') .config(['$controllerProvider', function($controllerProvider) { $controllerProvider.allowGlobals(); }]);
                        • -1。这也是确保 (a) 在升级后立即覆盖它的好方法,这将生成不必要的(和不正确的)报告“将 1.4.3 升级到 1.4.4 破坏了我的应用程序!”和/或 (b) 你不升级你的应用是因为“这很难”。
                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2014-02-26
                        • 2017-04-08
                        • 1970-01-01
                        相关资源
                        最近更新 更多