16

What issues might I experience in having two different versions of AngularJS loaded into one page?

Obviously this seems like a stupid thing to do, but my use case is a page that uses AngularJS incorporating a third-party component that drags in its preferred version of AngularJS.

Update:

Found some info:

https://groups.google.com/forum/#!msg/angular/G8xPyD1F8d0/u1QNDNvcwW4J https://github.com/angular/angular.js/pull/1535

falinsky
  • 7,229
  • 3
  • 32
  • 56
fadedbee
  • 42,671
  • 44
  • 178
  • 308

4 Answers4

9

Angular is really not prepared to co-exist with other version. But it's feasible.

First of all load angular library and make sure that before loading window.angular is empty:

  <script src="vendor/angular/1.2.0/angular.min.js"></script>
  <script src="app/app2.js"></script>
  <script>
    var angular2 = angular;
    window.angular = null; // here we're cleaning angular reference
  </script>

  <script src="vendor/angular/1.0.5/angular.js"></script>
  <script src="app/app1.js"></script>
  <script>
    var angular1 = angular;
  </script>

Note that each application (app1.js, app2.js) for each version of angular should be loaded immediately after loading angular library.

Each JavaScript file of the application shoud be wrapped in self executing function (function(angular) { ... })(angular). Look at the example of app2.js:

(function(angular) {

angular.module('myApp2', []).

controller('App2Ctrl', function($scope) {
    $scope.$watchCollection('[a, b, c]', function() {
        console.log(angular.version.full);
    });
});

})(angular);

Note that here I'm using $watchCollection which is only available for angular 1.2.x. By providing scope of anonymous function for each file you are forcing application to reach angular property instead of window.angular property.

Finally you have to bootstrap the application using manuall method:

<body>

  <div id="myApp1" ng-controller="App1Ctrl">
  </div>

  <div id="myApp2" ng-controller="App2Ctrl">
  </div>

  <script>
    angular1.bootstrap(document.getElementById('myApp1'), ['myApp1']);
    angular2.bootstrap(document.getElementById('myApp2'), ['myApp2']);
  </script>
</body>

Working plunker here. After running please check console window to see logged versions of angular used.

Deepzz
  • 4,573
  • 1
  • 28
  • 52
kseb
  • 712
  • 4
  • 12
  • This answer doesn't speak to namespacing the built-in angular directives, CSS classes or other objects that could conflict. Also, Removing window.angular then reloading it with a new version would, most likely, break the other persons angular application. – Alberto Ponte Dec 31 '13 at 09:21
  • 1
    Great solution! I would try and go even one step further and rename `angular` on the built widget so that it's called `myAngular` and load it: (function(angular) { angular.module('myApp2', []) })(myAngular); – amit Apr 28 '14 at 12:28
  • I don't think this solution is something to put on production. First problem I see: deleting window.angular for each angular scripts means each time I remove that variable the already loaded apps cannot work. Second problem: Last time an angular script is loaded window.angular is not deleted. So that's the new default angular version available. Third problem: in the example app1.js and app2.js the "angular" object is called to create modules. It means window.angular, only the last one, to create apps supposedly for different versions of angular. So why should I create angular1 and angular2? – David Vartanian Aug 25 '15 at 10:37
  • Something else to think of is that usually we could need simultaneous multiple angular versions when we develop a widget or something embeddable on third-party websites. So we have to think that we can control only one of those angular versions. So, reading the angular script code, which is stuck on window, what about emulating another window instead of removing angular? – David Vartanian Aug 25 '15 at 10:40
  • Hi @kseb, I've similar problem on my project. Do you have any idea on that one too? https://stackoverflow.com/questions/44668089/using-multiple-angularjs-versions-in-a-project-with-bower?noredirect=1#comment76321581_44668089 – Prometheus Jun 21 '17 at 07:07
3

Great question! Like you, we were unable to uncover much on this topic...we are in the process of deploying a version of Angular with our product which will be embedded within client websites that could also have Angular already loaded.

Here is what we have done:

  1. Modify the Angular source - do not use "window.angular" or "angular" in your implementation, choose some other variable or object property to house it. If you do use "window.angular" and/or "angular", it could break both applications if the versions are different.
  2. Rename all delivered objects (directives, etc); otherwise, the other version of angular could attempt to process your directives.
  3. Rename all CSS classes used by Angular (ng-cloak, etc). This will allow you to style your version of Angular separately from the other version.
  4. Manually bootstrap your application, as described by 'kseb' above.

If you are going to completely name space AngularJS as I have described here, take care to not do a global search and replace because angular does need a "window" reference for registering events, and a few other places.

I just finished doing this at work and I am in the process of testing. I will update this answer with my results.

Alberto Ponte
  • 479
  • 3
  • 7
  • Alberto: can you share your results? – johntday May 14 '14 at 20:08
  • @albertpeiro we haven't had to move on it because none of our clients are experiencing issues. – Alberto Ponte Jul 25 '14 at 21:04
  • Great to know! Any chance you could share with us specific steps / script/ operations you followed? I'm stuck with find/replace over angular.js I'd really appreciate a regular expression or steps for replacing all ng- prefixes. – albertpeiro Jul 27 '14 at 00:19
  • @albertpeiro feel free to email me to discuss, email addy is on my profile here. We manually renamed them because regEx search/replace was not a viable solution. – Alberto Ponte Aug 01 '14 at 18:44
  • @AlbertoPonte I can't see your email - I guess it's private. Thank you for help! – albertpeiro Aug 02 '14 at 19:40
2

Matt Burke describes a process to wrap the Angular JS libs in a function to create a closure. Downside is that you cannot load Angular via a public CDN as you have customized the download.

http://www.mattburkedev.com/multiple-angular-versions-on-the-same-page/

Remento
  • 927
  • 4
  • 6
1

Angular 2 will provide a new router with similar features to UI router, but that will also allow to have some routes in Angular 1 and others in Angular 2.

This router is currently being backported to Angular 1, see here a presentation from the developer of the new router explaining how this will work.

The idea behind a common cross-version router with support for both version is to help users upgrade from Angular 1 to Angular 2.

Angular University
  • 42,341
  • 15
  • 74
  • 81