Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular + Requirejs - Loading in the wrong order

I'm trying to have angular and jquery loaded with requirejs. The best I can do is that 50% of the time everything loads correctly, the other half I get the error No Module: mainApp

I'm assuming this is breaking half the time based on the speed on which requirejs is asynchronously loading the scripts.

When it works, I see the "Hello World" test (although I do see {{text}} flash before it is replaced, but I've been reading how to fix that here). The rest of the time I get the error and {{text}} just stays on the screen.

Github Repo

Tree:

index.html
- js
    - libs
        require.js
    - modules
        mainApp.js
    main.js

main.js

require.config({
  paths: {
    'jQuery': '//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min',
    'angular': '//ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular',
  },
  shim: {
    'angular' : {'exports' : 'angular'},
    'jQuery': {'exports' : 'jQuery'}
  }
});

require(['jQuery', 'angular', 'modules/mainApp'] , function ($, angular, mainApp) {
  $(function () { // using jQuery because it will run this even if DOM load already      happened
    angular.bootstrap(document, ['mainApp']);
  });
});

modules/mainApp.js

define(['angular'], function (angular) {
  return angular.module('mainApp' , []).controller('MainCtrl', ['$scope', function ($scope) {
      $scope.text = 'Hello World';
  }]);
});

Relevant index.html

<head>
    <script src="js/libs/require.js" data-main="js/main"></script>
</head>
<body>
    <div ng-app="mainApp">
        <div ng-controller="MainCtrl">
            {{text}}
        </div>
    </div>
</body>
like image 578
Nick Brown Avatar asked Mar 19 '26 02:03

Nick Brown


2 Answers

You can use domReady (UPDATED) to make sure that the DOM is fully loaded, i.e. all JS files are there, before bootstrapping your application.

requirejs.config({
    paths: {
        jquery: '/path/to/jquery',
        angular: 'path/to/angular',
        domReady: '/path/tp/domReady'
    }, shim: {
        angular: {
            exports: 'angular'
        },  
    }   
});
define(['jquery', 'angular', 'modules/mainApp'], 
    function($, angular, 'mainApp') {
        // tell angular to wait until the DOM is ready
        // before bootstrapping the application
        require(['domReady'], function() {
            angular.bootstrap(document, ['mainApp']);
        }); 
});

See the RequireJS official documentation for more information on this gotcha:

It is possible when using RequireJS to load scripts quickly enough that they complete before the DOM is ready. Any work that tries to interact with the DOM should wait for the DOM to be ready.

The trick is found on this blog post.

EDIT If you follow the blog post's advice, please use this domReady script instead of the one I previously posted: https://github.com/requirejs/domReady/blob/master/domReady.js.

like image 125
Lim H. Avatar answered Mar 21 '26 16:03

Lim H.


Add Jquery as a dependency for Angular in the shim.

require.config({
      paths: {
        'jQuery': '//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min',
        'angular': '//ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular',
      },
      shim: {
        'angular' : {'exports' : 'angular', deps: ['jQuery']},
        'jQuery': {'exports' : 'jQuery'}
      }
});
like image 38
Rob Avatar answered Mar 21 '26 16:03

Rob



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!