angular / angular.js

AngularJS - HTML enhanced for web apps!
https://angularjs.org
MIT License
58.8k stars 27.48k forks source link

Angular doesn't find module - why? #13133

Closed SetTrend closed 9 years ago

SetTrend commented 9 years ago

I have set up a simple and small text application for using ui-grid/RequireJS.

My problem with the setup below is that Angular starts searching for the ng-app directive before the HTML has finished loading. So randomly I get an Angular error stating that module "gridtest" could not be found:

 [$injector:modulerr] Failed to instantiate module gridtest due to:

Error: [$injector:nomod] Module 'gridtest' 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.

http://errors.angularjs.org/1.4.7/$injector/nomod?p0=gridtest
   at Anonymous function (http://localhost:2920/_Mocks/uiGuid/js/angular.js:1986:11)
   at ensure (http://localhost:2920/_Mocks/uiGuid/js/angular.js:1910:5)
   at module (http://localhost:2920/_Mocks/uiGuid/js/angular.js:1984:7)
...

What am I doing wrong? Why is AngularJS searching for the module before the DOM has completely been loaded?

Here's my source:

require(["uiGrid"], function ()
{
    angular.module("gridtest", ["ui.grid"])
    .factory("loaddata", ["$http", function ($http)
    {
        return function ()
        {
            return [
                { name: "John", Address: "Texas" },
                { name: "Doe", Address: "Florida" }
            ];
        };
    }])
    .controller("gridCtrl", ["$scope", "loaddata", function ($scope, loaddata)
    {
        $scope.data = loaddata();
    }]);
});
<!DOCTYPE html>
<html>
<head>
    <title>jqGrid Test Page</title>
    <link type="text/css" rel="stylesheet" href="css/ui-grid.min.css" />
</head>
<body ng-app="gridtest">
    <div ng-controller="gridCtrl" style="padding: 2em; background-image: linear-gradient(rgb(56,77,112), white)">
        <div ui-grid="{ data: data }"></div>
    </div>

    <script type="text/javascript">
        var require =
            {
                paths:
                    {
                        jquery: "../../../Content/js/jquery-2.1.4/jquery-2.1.4.min",
                        angular: "angular",
                        uiGrid: "ui-grid.min"
                    },
                shim:
                    {
                        "angular": { deps: ["jquery"] },
                        "uiGrid": { deps: ["angular"] }
                    }

            };
    </script>
    <script type="text/javascript" src="js/require.js" defer="defer" data-main="js/GridTest.js"></script>
</body>
</html>
tomtom87 commented 9 years ago

You must set the ng-app directive inside of the <html> tag e.g

<!DOCTYPE html>
<html ng-app="gridtest">
<head>
    <title>jqGrid Test Page</title>
    <link type="text/css" rel="stylesheet" href="css/ui-grid.min.css" />
</head>
SetTrend commented 9 years ago

Just tried. It doesn't make a difference.

... and many StackOverflow answers confirm that it doesn't make a difference.

tomtom87 commented 9 years ago

Wait sorry that was full retard of me. It's because you don't have the module gridtest loaded into your page mate, you need to set a <script> for it - unless that js/require.js is doing it. You want double check it and see there in the console if you can access the gridtest module first.. safe

SetTrend commented 9 years ago

No problem. I happen to regularly boob myself, too ;)

But your new reply isn't helpful, either, I'm afraid. As you can see from the code snippets, module gridtest actually exists. And it's getting loaded - occasionally. But occasionally it isn't.

I assume, AngularJS doesn't well co-operate with RequireJS. Is this assumption true? Or did I do something wrong here?

JustinBeaudry commented 9 years ago

It looks like your using a deferred script loader. That could be a problem for the use of the ng-app directive. If DOMContentLoaded has fired then ng-app will automagically call angular.bootstrap and if you haven't loaded all the scripts required to run your app, you're going to run into problems. So you may need to manually bootstrap your angular application once you're certain that all scripts have been loaded. https://docs.angularjs.org/guide/bootstrap#manual-initialization

SetTrend commented 9 years ago

I understand. Yet the problem is not that I need to manually initialize AngularJS, but instead that AngularJS is throwing an exception, and I'm not able to suppress this exception.

robwormald commented 9 years ago

this is an either / or decision: you either use ng-app="yourapp" in your HTML, or you use angular.bootstrap(document, ['yourapp']); - using both doesn't work.

robwormald commented 9 years ago

other note: you'll find that with async loading, its possible you'll see a flash of {{binding}} tags before angular bootstraps - the ng-cloak directive is useful for handling this scenario.

robwormald commented 9 years ago

all of that said, one pretty hard and fast requirement of angular is that all modules be loaded before bootstrapping - that is, you can't lazy-load a module at some point after the application has bootstrapped.

Narretz commented 9 years ago

thanks @robwormald for solving this!

lafiza commented 7 years ago

this is still a issue for me

. . . . .
bernardoadc commented 6 years ago

You normally can't lazy load, but with oclazyload you can. In case it helps someone..

Also, there is a way to load providers (within same modules) at the moment some template loads as well