6

I need dynamically add script in my index.html page depending on the application version. I have a controller that returns app version and tried to do this using angularjs:

    var resourceLoader = angular.module('MyTabs', []);
    resourceLoader.controller('ResourceLoaderController', ['$scope', '$http', function ($scope, $http) {
        $scope.getVersion = function() {
            $http.get('/version/get').then(function (response) {
                $scope.version = response.data;
                var link = document.createElement("link");
                link.setAttribute("type", "text/css");
                link.setAttribute("rel", "stylesheet");
                link.setAttribute("href", '/r/' + $scope.version +'/css/app.css');
                document.getElementsByTagName("head")[0].appendChild(link);

                var script = document.createElement("script");
                script.setAttribute("type", "text/javascript");
                script.setAttribute("src", '/r/' + $scope.version +'/js/app.js');
                document.getElementsByTagName("head")[0].appendChild(script);
            });
        };

        $scope.getVersion();
    }]);

It works but there are angular controllers in app.js, and I get an error in runtime that AuthController, used in index.html, is undefined.

Is there any way to get application version from server and include script before angularjs starts processes the web page?

Kirill
  • 1,540
  • 4
  • 18
  • 41
  • What do you mean by application version? Of angular? – Daniel Lizik Dec 23 '15 at 14:39
  • upvote for both questions because you didn't change [previous one](http://stackoverflow.com/questions/34433750/get-script-location-from-server) when next issue was found. – Jordi Castilla Dec 23 '15 at 14:44
  • Application version is a number that "/version/get" returns. Angular - is js framework (https://angularjs.org/) – Kirill Dec 23 '15 at 14:45
  • Typically, an application doesn't get its own version number at runtime. You might deploy multiple versions of the same app, using e.g. /v2 or /v3 in the URL to differentiate...so I'm curious why you wouldn't just handle versioning in your build process. – Shaun Scovil Dec 23 '15 at 16:31

3 Answers3

1

How AngularJS works is it creates the app and builds all controller/directives/services dictionaries when you include the .js files.

By adding another script after AngularJS has finished building those, the controllers won't get added to the app.

You need to look up how to add controllers dynamically: Loading an AngularJS controller dynamically

Your other choice is getting the version and script BEFORE your html references and builds the AngularJS dependency. This way by the time AngularJS starts doing its magic, the scripts already will be loaded.

Community
  • 1
  • 1
AlexD
  • 4,062
  • 5
  • 38
  • 65
0

interesting question.

You could, get the version in a normal script tag in the head of the HTML document, making sure it is loaded synchronously, which is the default I believe (script tags I believe are loaded synchronously even when async operations are performed within them). That script would add a CSS class onto head to represent the version number.

Then afterwards you could load angular in a script tag and then do ...

<script ng-if="version==='something'" src='/somePath'></script>

for conditional script tags.

Hope that helps.

Alternatively use Node's grunt or gulp to start a server which makes an HTTP request to get the version and then writes the index.html page according to the version and then starts the server.

Worth noting that Node's wiredep auto includes script tags into index.html based on bower components.

I feel that the grunt or gulp approach is the more natural although it still seems that 60+% of the webdev community are still living in the web's dark ages and have never used or heard of Node or grunt or gulp. lol.

danday74
  • 52,471
  • 49
  • 232
  • 283
0

Thank you for answers. I fixed problem this way:

<script>
    var xmlhttp;

    if (window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest();
    } else {
        xmlhttp = new ActiveXObject("Microsoft.XMLXTTP");
    }

    function getVersion() {
        xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                var version = xmlhttp.responseText;
                var link = document.createElement("link");
                link.setAttribute("type", "text/css");
                link.setAttribute("rel", "stylesheet");
                link.setAttribute("href", '/r/' + version +'/css/app.css');
                document.getElementsByTagName("head")[0].appendChild(link);

                var script = document.createElement("script");
                script.setAttribute("type", "text/javascript");
                script.setAttribute("src", '/r/' + version +'/js/app.js');
                document.getElementsByTagName("head")[0].appendChild(script);
            } else if (xmlhttp.status != 200) {
                console.log("Something went wrong. HTTP Status: " + xmlhttp.status);
            }
        };
        xmlhttp.open("GET", "version/get" , true);
        xmlhttp.send();
    }
    getVersion();
</script>
Kirill
  • 1,540
  • 4
  • 18
  • 41