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

4 Answers 4

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.

Sign up to request clarification or add additional context in comments.

5 Comments

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.
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);
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?
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?
Hi @kseb, I've similar problem on my project. Do you have any idea on that one too? stackoverflow.com/questions/44668089/…
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.

5 Comments

Alberto: can you share your results?
@albertpeiro we haven't had to move on it because none of our clients are experiencing issues.
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 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.
@AlbertoPonte I can't see your email - I guess it's private. Thank you for help!
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/

Comments

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.

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.