Search code examples
javascriptjqueryangularjsfirebaseangularfire

Angular Module not available when using $(document).ready()


I'm getting a curious error similar to some other posts, but I haven't been able to remedy. I'm using jQuery's document.ready() to ensure that all the buttons are loaded before referencing my local Javascript file that includes an AngularJS front-end incorporated with Firebase and Angularfire.

I'm getting the following error in the console that typically accompanies an Angular controller with an unreferenced or uninitialized dependency injection:

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

I wrote this code while following this tutorial on Youtube and basically copied everything the same except including the aforementioned jQuery.

Index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Piano Lessons Administrator Signup</title>

    <!--Jquery-->
    <script
            src="https://code.jquery.com/jquery-3.2.1.min.js"
            integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
            crossorigin="anonymous"></script>

    <!--AngularJS-->
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.js"></script>

    <!--Firebase Dependency-->
    <script src="https://www.gstatic.com/firebasejs/4.8.0/firebase.js"></script>

    <!-- AngularFire -->
    <script src="https://cdn.firebase.com/libs/angularfire/2.3.0/angularfire.min.js"></script>

    <!--Local Javascript-->
    <script>
    $(document).ready(function(){
      $(function(){
          $.getScript('javascripts/piano.js');  
      });
    });
    </script>
    </head>


   <body ng-app="myApp">
      <div ng-congroller="MyCtrl as ctrl">

        <pre>{{ ctrl.object | json }} </pre>

      </div> <!--End myCtrl-->
   </body>

...
</html>

...and Piano.js

(function () {

// Initialize Firebase
var config = {
    apiKey: "myApikey",
    authDomain: "myAuthDomain",
    databaseURL: "myDatabaseURL",
    projectId: "projectId",
    storageBucket: "myStorageBucket",
    messagingSenderId: "MyMessagingSender"
};
firebase.initializeApp(config);

var myApp = angular
    .module('myApp', ['firebase'])
    .config(function ($firebaseRefProvider) {
    $firebaseRefProvider.registerUrl({
        default: config.databaseURL,
        object: `${config.databaseURL}/angular/object`
    });  
})
    .factory('ObjectFactory', ObjectFactory)
    .controller('MyCtrl', MyCtrl);

function ObjectFactory($firebaseObject, $firebaseRef){
    return $firebaseObject($firebaseRef.object);
}

function MyCtrl(ObjectFactory){
    this.object = ObjectFactory;
    this.sayHello = () => {
    //console.log(this.object.name);
        return `Hello, ${this.object.name}`;
    }
}

const ctrl = new MyCtrl({ name: 'David' });
const message = ctrl.sayHello();
console.log(message);

...
}());

Interestingly, The console.log(message) does seem to work, which seems like it would need the module to be working for the controller and factory to be working, but the object in the tag does not compile leaving it plain text, which usually means the controller has failed. Does putting it inside the $(document).ready() take the other tags out of scope?


Solution

  • Since the module is loaded after the DOMContentLoaded event, the app needs to be manually bootstrapped.

    First remove the auto-bootstrap directive:

     <body ̶n̶g̶-̶a̶p̶p̶=̶"̶m̶y̶A̶p̶p̶"̶ >
    

    Then manually bootstrap the app after the module has been loaded:

    $(document).ready(function(){
      $(function(){
          $.getScript('javascripts/piano.js');
          angular.bootstrap(document.body, ['myApp']);  
      });
    });
    

    For more information, see