0

We have a product that is a widget people load onto their site, which consists of a single JS file that also needs angular to run, so angular is bundled into the JS file.

However, if a site already is using and loading angular themselves, when they load our widget they get an error which kills everything with the following:

WARNING: Tried to load angular more than once

Which makes complete sense since angular was indeed loaded more than once.

What we'd like to do is either of the following:

  1. In our script, rename / namespace angular so it does't conflict with the host sites already loaded angular, or
  2. Detect if angular is already loaded, and if so don't load angular ourselves.

To show examples of our code would be difficult since it's spread over about 20 files etc, however it's based off the following angular seed project which uses requirejs to load everything, then we're compiling to a single file: https://github.com/tnajdek/angular-requirejs-seed

Would really appreciate any feedback / tips / solutions

NB This is not a duplicate of any "check if angular loaded correctly" type questions, angular is packaged inside our widget js, the issue comes when angular is also already loaded by the parent page. We need a way to rename angular inside our package.

duellsy
  • 8,497
  • 2
  • 36
  • 60
  • http://stackoverflow.com/questions/22595878/tried-to-load-angular-more-than-once – Lokesh Oct 31 '14 at 06:52
  • thanks, but that is in no way relevant. the script works completely fine, it's only when it is loaded on a site that already loads angularJS as the above states. – duellsy Oct 31 '14 at 06:55
  • put your widget in an iframe? – Lucius Oct 31 '14 at 07:56
  • an iframe is not a valid solution to our problem, we need to have two way messaging with the parent page, we have moved away from an iframe version towards angular based. – duellsy Oct 31 '14 at 23:28
  • 1
    Detecting and leveraging an existing Angular load could be sticky, as you have know way of assuring that something in the source hasn't been changed, plus it needs to be the proper version. Namespacing could work though - here's a pretty solid article on the topic: http://www.mattburkedev.com/multiple-angular-versions-on-the-same-page/ – Shawn Erquhart Nov 01 '14 at 02:38
  • thanks @ShawnErquhart I've actually attempted that solution, but having issues with being able to bootstrap, it thinks angular no longer exists for some reason – duellsy Nov 03 '14 at 07:00

1 Answers1

2

I'd advise taking a look at this answer, it has to do with a chrome extension running in the same circumstance. The idea here is to separate your loading of angular from the website's, and it assumes that your widget will be loaded after the main content of the page has been loaded.

  1. If you are loading in html content with an ng-app directive or ng-controller, wrap your html content in a container with ng-non-bindable as an attribute.
  2. Angular looks immediately for an element with the ng-app attribute when you load in angular.js. If two ng-apps are present i.e., on your site, and the widget, it will cause errors. Defer the parsing with: window.name = "NG_DEFER_BOOTSTRAP!" + window.name; Then load in your script.
  3. Once your script has loaded, set window.name to '' or whatever it was before.
  4. Individually bootstrap (the term for angular finding an ng-app attribute) your html content using:

    var appRoot = document.querySelector('#id');
    
    angular.bootstrap(appRoot, ['angularModuleName']);
    

And that should do it... Caveat, I have no idea how this would work if your widget Angular is on a different version than the client website, and I've only made it work with extensions, which are a little bit different because they live in their own isolated 'worlds'.

That being said, I feel like this should get people going in the right direction when dealing with this problem.

Community
  • 1
  • 1
SethWhite
  • 1,891
  • 18
  • 24