AngularJS–[ng:areq] Argument ‘xxCtrl’ is not a function, got undefined! Error (Fixed)

In the Angular Chinese community, we sometimes hear students asking about “ng:areq” errors:

 [ng:areq] Argument 'DemoCtrl' is not a function, got undefined!

This is often due to forgetting to define a Controller or declaring a module multiple times, which will cause the previous module definition information to be cleared, so the application will not find the defined component. We also know this from the Angular source (from Loader.js) :

function setupModuleLoader(window) {
            ...
            function ensure(obj, name, factory) {
                return obj[name] || (obj[name] = factory());
            }
            var angular = ensure(window, 'angular', Object);
            return ensure(angular, 'module', function() {
                var modules = {};
                return function module(name, requires, configFn) {
                    var assertNotHasOwnProperty = function(name, context) {
                        if (name === 'hasOwnProperty') {
                            throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
                        }
                    };

                    assertNotHasOwnProperty(name, 'module');
                    if (requires && modules.hasOwnProperty(name)) {
                        modules[name] = null;
                    }
                    return ensure(modules, name, function() {
                        if (!requires) {
                            throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
                                "the module name or forgot to load it. If registering a module ensure that you " +
                                "specify the dependencies as the second argument.", name);
                        }
                        var invokeQueue = [];
                        var runBlocks = [];
                        var config = invokeLater('$injector', 'invoke');
                        var moduleInstance = {
                            _invokeQueue: invokeQueue,
                            _runBlocks: runBlocks,
                            requires: requires,
                            name: name,
                            provider: invokeLater('$provide', 'provider'),
                            factory: invokeLater('$provide', 'factory'),
                            service: invokeLater('$provide', 'service'),
                            value: invokeLater('$provide', 'value'),
                            constant: invokeLater('$provide', 'constant', 'unshift'),
                            animation: invokeLater('$animateProvider', 'register'),
                            filter: invokeLater('$filterProvider', 'register'),
                            controller: invokeLater('$controllerProvider', 'register'),
                            directive: invokeLater('$compileProvider', 'directive'),
                            config: config,
                            run: function(block) {
                                runBlocks.push(block);
                                return this;
                            }
                        };
                        if (configFn) {
                            config(configFn);
                        }
                        return moduleInstance;

                        function invokeLater(provider, method, insertMethod) {
                            return function() {
                                invokeQueue[insertMethod || 'push']([provider, method, arguments]);
                                return moduleInstance;
                            };
                        }
                    });
                };
            });
        }

In the code, we learn that Angular sets the global Angular object at startup and publishes the Module API on the Angular object. For the module API code, you can clearly see the first predicate sentence, module name cannot be named after hasOwnProperty, otherwise it will throw the “badname” error message. Next, if the name parameter is passed in, which represents a declaration of a module, the existing module information is deleted and set to null.
From the definition of moduleInstance, we can see that the apis exposed for us are: invokeQueue, runBlocks, Requires, provider, Factory, Servic, value, Constant, animation, Filter, Controller, directive, config, run. InvokeQueue and runBlocks is as agreed in the name of the private property, please do not use other apis are our common presents component definition method, see this class presents the invokeLater code from the component definition of return is still moduleInstance instances, this creates a fluent API, it is recommended to use chain defines these components, rather than a statement of a global module variables.
Finally, if the third parameter, configFn, is passed in, it will be configured into the config information. When Angular enters the config phase, they will in turn execute the pre-instantiation configuration for Angular applications or Angular components such as services.

Read More: