0

I am trying to write an anonymous javascript function that dynamically loads jquery and angular. However, when I run the function I keep getting 'jQuery is not a function'. Can someone help? Here is my code:

(function() {

  var jQuery;
  var jquery_tag = document.createElement('script');
  var angular_tag = document.createElement('script');

  jquery_tag.setAttribute("type", "text/javascript");
  jquery_tag.setAttribute("src", "https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js");

  angular_tag.setAttribute("type", "text/javascript");
  angular_tag.setAttribute("src", "https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js");

  jquery_tag.onload = scriptLoadHandler;
  angular_tag.onload = scriptLoadHandler;

  (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(jquery_tag);
  (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(angular_tag);


  function scriptLoadHandler() {
    jQuery = window.jQuery
    main();
  }

  function main() {
    jQuery(document).ready(function($) {
      alert('yo'); //this runs
    });
  }

})();

Here is my fiddle:

https://jsfiddle.net/p7jcofx1/4/

Thanks in advance!

7
  • 1
    Can you update your jsfiddle to reflect your recent code changes? Commented May 18, 2016 at 15:03
  • Also, where exactly are you getting the error 'jQuery is not a function'? Commented May 18, 2016 at 15:06
  • What would happen if angular loads before jQuery? Commented May 18, 2016 at 15:06
  • @apokryfos It would use inbuild jqLite Commented May 18, 2016 at 15:07
  • 1
    @A.Wolff yes but would jQuery exist? Commented May 18, 2016 at 15:09

2 Answers 2

3

scriptLoadHandler() will run two times based on this code:

jquery_tag.onload = scriptLoadHandler;
angular_tag.onload = scriptLoadHandler;

Even though the Angular code is listed after the jQuery code, it could load first, making window.jQuery undefined in scriptLoadHandler, and causing jQuery(document) to fail in main().

You can prevent this by updating scriptLoadHandler as follows:

function scriptLoadHandler() {
  if(window.jQuery) {
    jQuery = window.jQuery
    main();
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

this solved it! also, if you don't mind, could you confirm that i'm loading the jquery and angular correctly / via best practices?
I honestly don't know what best practices are for loading scripts dynamically, but I don't see anything wrong with your code other than the risk that Angular could load first.
1

From the angular documentation here

To use jQuery, simply ensure it is loaded before the angular.js file. You can also use the ngJq directive to specify that jqlite should be used over jQuery, or to use a specific version of jQuery if multiple versions exist on the page.

You can achieve this using the following:

  var jquery_tag = document.createElement('script');          

  jquery_tag.setAttribute("type", "text/javascript");
  jquery_tag.setAttribute("src", "https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js");          

  jquery_tag.onload = jQueryLoadedHandler;    

  (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(jquery_tag);      


  function jQueryLoadedHandler() {
    //Load angular after jQuery 
    var angular_tag = document.createElement('script');
    angular_tag.setAttribute("type", "text/javascript");
    angular_tag.setAttribute("src", "https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js");
    angular_tag.onload = angularLoadedHandler;
    (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(angular_tag);
  }

  function angularLoadedHandler() {         
      main(); //Both jQuery and angular should be loaded
  }

  function main() {
    jQuery(document).ready(function($) {
      alert('yo'); //this runs
    });
  }

Updated fiddle

Note: This is a suggestion in the case you want angular.js to use jQuery. If you don't mind it using jqLite then this is not necessary and the accepted answer should work just fine.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.